This is an R Markdown Notebook that describes the techniques for evaluating the Predictive Analytics Tool and their results. The results from the executed code appear beneath the code itself.

Installing required libraries:
readxl, plotly and ggplot2
options(warn=-1)
require(readxl)
require(plotly)
require(ggplot2)
set.seed(8274)



Importing data for analysis:
Prices, PAT output and Timeline For Client Responses
prices <- read_excel("/Users/shubhankar/Desktop/PRI/prices.xlsx", 1, col_names = TRUE)
pat_output <- read_excel("/Users/shubhankar/Desktop/PRI/PAT_output.xlsx", 1, col_names = TRUE)
client_response_2014 <- read_excel("/Users/shubhankar/Desktop/PRI/TimelineForClientResponses.xlsm", 4, col_names = TRUE)
client_response_2015 <- read_excel("/Users/shubhankar/Desktop/PRI/TimelineForClientResponses.xlsm", 5, col_names = TRUE)
client_response_2016 <- read_excel("/Users/shubhankar/Desktop/PRI/TimelineForClientResponses.xlsm", 6, col_names = TRUE)
client_response_2017 <- read_excel("/Users/shubhankar/Desktop/PRI/TimelineForClientResponses.xlsm", 7, col_names = TRUE)



Basic housekeeping:
Formatting first column as date, setting time-zone.
prices = as.data.frame(prices)
pat_output = as.data.frame(pat_output)
Sys.setenv(tz = Sys.timezone())
invisible(as.POSIXct(prices$Date, tz=getOption("tz")))
invisible(as.POSIXct(pat_output$Date, tz=getOption("tz")))



Plotting calendar year Prices vs Time.
A detailed plot can be viewed here
plot_ly(prices, x = prices$Date, y = prices$Y_14, name = 'Y_14', type = "scatter", mode = 'lines', line = list(width = 1), width = 950) %>%
  add_trace(y = prices$Y_15, name = 'Y_15', mode = 'lines') %>%
  add_trace(y = prices$Y_16, name = 'Y_16', mode = 'lines') %>%
  add_trace(y = prices$Y_17, name = 'Y_17', mode = 'lines') %>%
  add_trace(y = prices$Y_18, name = 'Y_18', mode = 'lines') %>%
  add_trace(y = prices$Y_19, name = 'Y_19', mode = 'lines') %>%
  add_trace(y = prices$Y_20, name = 'Y_20', mode = 'lines') %>%
  add_trace(y = prices$Y_21, name = 'Y_21', mode = 'lines') %>% 
  layout(hovermode="compare")



Plotting AM Prices vs Time.
A detailed plot can be viewed here
plot_ly(prices, x = prices$Date, y = prices$Y_14AM, name = 'Y_14AM', type = "scatter", mode = 'lines', line = list(width = 1), width = 950) %>%
  add_trace(y = prices$Y_15AM, name = 'Y_15AM', mode = 'lines') %>%
  add_trace(y = prices$Y_16AM, name = 'Y_16AM', mode = 'lines') %>%
  add_trace(y = prices$Y_17AM, name = 'Y_17AM', mode = 'lines') %>%
  add_trace(y = prices$Y_18AM, name = 'Y_18AM', mode = 'lines') %>%
  add_trace(y = prices$Y_19AM, name = 'Y_19AM', mode = 'lines') %>%
  add_trace(y = prices$Y_20AM, name = 'Y_20AM', mode = 'lines') %>%
  layout(hovermode="compare")



Plotting distribution of prices for each calendar year and corresponding fiscal year:
Y_14 and Y_14AM, Y_15 and Y_15AM, Y_16 and Y_16AM, Y_17 and Y_17AM, Y_18 and Y_18AM, Y_19 and Y_19AM, Y_20 and Y_20AM, Y_21 and Y_21AM
x_axis_template <- list(showgrid = F,
                      zeroline = F,
                      nticks = 20,
                      showline = T,
                      tick0 = 0,
                      range = c(28,45),
                      title = "Prices")
y_axis_template <- list(nticks = 8, range = c(0,120), title = "Frequency")
strips <- list("Y_14", "Y_15", "Y_16", "Y_17", "Y_18", "Y_19", "Y_20", "Y_21")
plots <- lapply(strips, function(var){
  AM <- paste(var,"AM", sep = "")
  plot_ly(width = 950) %>%
  add_histogram(x = prices[,var], name = var) %>%
  add_histogram(x = prices[,AM], name = AM) %>%
  layout(xaxis = x_axis_template, yaxis = y_axis_template, hovermode="compare")
})
subplot(plots, nrows = 4, shareX = TRUE, shareY = TRUE)
Ignoring 736 observationsIgnoring 695 observationsIgnoring 582 observationsIgnoring 536 observationsIgnoring 351 observationsIgnoring 362 observationsIgnoring 176 observationsIgnoring 183 observationsIgnoring 143 observationsIgnoring 279 observationsIgnoring 279 observationsIgnoring 467 observationsIgnoring 467 observationsIgnoring 719 observationsIgnoring 719 observationsIgnoring 767 observations



Since the number of days of historical data to use in calculations is set to 100 days therefore we skip the prices for first 100 days in each strip and use the subsequent prices to generate recommendations. As a consequence of skipping we are left with no prices for the strip Y_14 and very few entries for the strip Y_14AM. Thus we will consider the prices of strips Y_14AM onwards for evaluating the PAT.


Preliminary Analysis

Split PAT output by respective contract years.

pat_output <- pat_output[order(pat_output$Contract), ]
Y_14AM <- pat_output[pat_output$Contract=="Y_14AM",]
Y_15 <- pat_output[pat_output$Contract=="Y_15",]
Y_15AM <- pat_output[pat_output$Contract=="Y_15AM",]
Y_16 <- pat_output[pat_output$Contract=="Y_16",]
Y_16AM <- pat_output[pat_output$Contract=="Y_16AM",]
Y_17 <- pat_output[pat_output$Contract=="Y_17",]
Y_17AM <- pat_output[pat_output$Contract=="Y_17AM",]



Scatter-line plots showing prices and distribution of hedging opportunities across time for each strip. A red dot represents “5 - Great hedging opportunity” and a yellow dot represents “4 - Very good hedging opportunity”.

#Y_14AM
plotY_14AM <- plot_ly(Y_14AM, x = Y_14AM$Date, y = Y_14AM$Price, name = 'Y_14AM', type = "scatter", mode = 'lines', line = list(width = 1), width = 950, height = 500) %>% layout(hovermode="compare", yaxis = list(title = "Price"), showlegend = T)
for(i in Y_14AM[Y_14AM$Recommendation == "5 - Great hedging opportunity",3]){
  plotY_14AM <- add_trace(plotY_14AM, x = (as.numeric(as.Date(Y_14AM[Y_14AM$Price == i,1])) * 24 * 60 * 60 * 1000), y = i, mode = "markers+lines", showlegend = F, marker = list(color="red", size=5, opacity=0.5))
}
for(i in Y_14AM[Y_14AM$Recommendation == "4 - Very good hedging opportunity",3]){
  plotY_14AM <- add_trace(plotY_14AM, x = (as.numeric(as.Date(Y_14AM[Y_14AM$Price == i,1])) * 24 * 60 * 60 * 1000), y = i, mode = "markers+lines", showlegend = F, marker = list(color="orange", size=5, opacity=0.5))
}
#Y_15
plotY_15 <- plot_ly(Y_15, x = Y_15$Date, y = Y_15$Price, name = 'Y_15', type = "scatter", mode = 'lines', line = list(width = 1), width = 950, height = 500) %>%
layout(hovermode="compare", yaxis = list(title = "Price"), showlegend = T)
for(i in Y_15[Y_15$Recommendation == "5 - Great hedging opportunity",3]){
  plotY_15 <- add_trace(plotY_15, x = (as.numeric(as.Date(Y_15[Y_15$Price == i,1])) * 24 * 60 * 60 * 1000), y = i, mode = "markers+lines", showlegend = F, marker = list(color="red", size=5, opacity=0.5))
}
for(i in Y_15[Y_15$Recommendation == "4 - Very good hedging opportunity",3]){
  plotY_15 <- add_trace(plotY_15, x = (as.numeric(as.Date(Y_15[Y_15$Price == i,1])) * 24 * 60 * 60 * 1000), y = i, mode = "markers+lines", showlegend = F, marker = list(color="orange", size=5, opacity=0.5))
}
#Y_15AM
plotY_15AM <- plot_ly(Y_15AM, x = Y_15AM$Date, y = Y_15AM$Price, name = 'Y_15AM', type = "scatter", mode = 'lines', line = list(width = 1), width = 950, height = 500) %>%
layout(hovermode="compare", yaxis = list(title = "Price"), showlegend = T)
for(i in Y_15AM[Y_15AM$Recommendation == "5 - Great hedging opportunity",3]){
  plotY_15AM <- add_trace(plotY_15AM, x = (as.numeric(as.Date(Y_15AM[Y_15AM$Price == i,1])) * 24 * 60 * 60 * 1000), y = i, mode = "markers+lines", showlegend = F, marker = list(color="red", size=5, opacity=0.5))
}
for(i in Y_15AM[Y_15AM$Recommendation == "4 - Very good hedging opportunity",3]){
  plotY_15AM <- add_trace(plotY_15AM, x = (as.numeric(as.Date(Y_15AM[Y_15AM$Price == i,1])) * 24 * 60 * 60 * 1000), y = i, mode = "markers+lines", showlegend = F, marker = list(color="orange", size=5, opacity=0.5))
}
#Y_16
plotY_16 <- plot_ly(Y_16, x = Y_16$Date, y = Y_16$Price, name = 'Y_16', type = "scatter", mode = 'lines', line = list(width = 1), width = 950, height = 500) %>%
layout(hovermode="compare", yaxis = list(title = "Price"), showlegend = T)
for(i in Y_16[Y_16$Recommendation == "5 - Great hedging opportunity",3]){
  plotY_16 <- add_trace(plotY_16, x = (as.numeric(as.Date(Y_16[Y_16$Price == i,1])) * 24 * 60 * 60 * 1000), y = i, mode = "markers+lines", showlegend = F, marker = list(color="red", size=5, opacity=0.5))
}
for(i in Y_16[Y_16$Recommendation == "4 - Very good hedging opportunity",3]){
  plotY_16 <- add_trace(plotY_16, x = (as.numeric(as.Date(Y_16[Y_16$Price == i,1])) * 24 * 60 * 60 * 1000), y = i, mode = "markers+lines", showlegend = F, marker = list(color="orange", size=5, opacity=0.5))
}
#Y_16AM
plotY_16AM <- plot_ly(Y_16AM, x = Y_16AM$Date, y = Y_16AM$Price, name = 'Y_16AM', type = "scatter", mode = 'lines', line = list(width = 1), width = 950, height = 500) %>%
layout(hovermode="compare", yaxis = list(title = "Price"), showlegend = T)
for(i in Y_16AM[Y_16AM$Recommendation == "5 - Great hedging opportunity",3]){
  plotY_16AM <- add_trace(plotY_16AM, x = (as.numeric(as.Date(Y_16AM[Y_16AM$Price == i,1])) * 24 * 60 * 60 * 1000), y = i, mode = "markers+lines", showlegend = F, marker = list(color="red", size=5, opacity=0.5))
}
for(i in Y_16AM[Y_16AM$Recommendation == "4 - Very good hedging opportunity",3]){
  plotY_16AM <- add_trace(plotY_16AM, x = (as.numeric(as.Date(Y_16AM[Y_16AM$Price == i,1])) * 24 * 60 * 60 * 1000), y = i, mode = "markers+lines", showlegend = F, marker = list(color="orange", size=5, opacity=0.5))
}
#Y_17
plotY_17 <- plot_ly(Y_17, x = Y_17$Date, y = Y_17$Price, name = 'Y_17', type = "scatter", mode = 'lines', line = list(width = 1), width = 950, height = 500) %>%
layout(hovermode="compare", yaxis = list(title = "Price"), showlegend = T)
for(i in Y_17[Y_17$Recommendation == "5 - Great hedging opportunity",3]){
  plotY_17 <- add_trace(plotY_17, x = (as.numeric(as.Date(Y_17[Y_17$Price == i,1])) * 24 * 60 * 60 * 1000), y = i, mode = "markers+lines", showlegend = F, marker = list(color="red", size=5, opacity=0.5))
}
for(i in Y_17[Y_17$Recommendation == "4 - Very good hedging opportunity",3]){
  plotY_17 <- add_trace(plotY_17, x = (as.numeric(as.Date(Y_17[Y_17$Price == i,1])) * 24 * 60 * 60 * 1000), y = i, mode = "markers+lines", showlegend = F, marker = list(color="orange", size=5, opacity=0.5))
}
#Y_17AM
plotY_17AM <- plot_ly(Y_17AM, x = Y_17AM$Date, y = Y_17AM$Price, name = 'Y_17AM', type = "scatter", mode = 'lines', line = list(width = 1), width = 950, height = 450) %>%
layout(hovermode="compare", yaxis = list(title = "Price"), showlegend = T )
for(i in Y_17AM[Y_17AM$Recommendation == "5 - Great hedging opportunity",3]){
  plotY_17AM <- add_trace(plotY_17AM, x = (as.numeric(as.Date(Y_17AM[Y_17AM$Price == i,1])) * 24 * 60 * 60 * 1000), y = i, mode = "markers+lines", showlegend = F, marker = list(color="red", size=5, opacity=0.5))
}
for(i in Y_17AM[Y_17AM$Recommendation == "4 - Very good hedging opportunity",3]){
  plotY_17AM <- add_trace(plotY_17AM, x = (as.numeric(as.Date(Y_17AM[Y_17AM$Price == i,1])) * 24 * 60 * 60 * 1000), y = i, mode = "markers+lines", showlegend = F, marker = list(color="orange", size=5, opacity=0.5))
}



Y_14AM
plotY_14AM



Y_15
plotY_15



Y_15AM
plotY_15AM



Y_16
plotY_16



Y_16AM
plotY_16AM



Y_17
plotY_17



Y_17AM
plotY_17AM



Violin plots showing price density and distribution of hedging opportunities across prices for each strip. Thicker the plot higher the frequency of the prices in that neighborhood. A red dot represents “5 - Great hedging opportunity” and a yellow dot represents “4 - Very good hedging opportunity”. Horizontal crossbar(black) shows the median price for that strip.

ggplot(width = 950, pat_output, aes(Contract, Price)) + geom_violin(aes(fill = Contract)) + scale_fill_manual(values=c("#B4E0D2", "#FCC6B3", "#C6CFE4", "#F2C5E0", "#D3EAAD", "#FEEBA1", "#F1E1CA")) + geom_point(data=pat_output[pat_output$Recommendation=="5 - Great hedging opportunity",], aes(Contract, Price), color = "#B40619", position = position_jitter(0.09), size = 0.5) + geom_point(data=pat_output[pat_output$Recommendation=="4 - Very good hedging opportunity",], aes(Contract, Price), color = "#E56621", position = position_jitter(0.09), size = 0.5) + stat_summary(fun.y = "median", fun.ymin ="median", fun.ymax ="median", geom ="crossbar", width=0.2, fatten = 1)



Boxplot showing median, first, second, third and fourth quartile of prices for each strip.

box1 <- plot_ly(pat_output, x = ~Contract, y = ~Price, color = ~Contract, type = "box", boxpoints = FALSE, width = 950) %>%
  layout(hovermode="compare")
hedge_price_boxplot <- data.frame(Contract = pat_output[pat_output$Recommendation == "5 - Great hedging opportunity" | pat_output$Recommendation == "4 - Very good hedging opportunity", "Contract"], Price = pat_output[pat_output$Recommendation == "5 - Great hedging opportunity" | pat_output$Recommendation == "4 - Very good hedging opportunity", "Price"])
box2 <- plot_ly(hedge_price_boxplot, x = hedge_price_boxplot$Contract, y = hedge_price_boxplot$Price, color = ~Contract, type = "box", boxpoints = FALSE, width = 950) %>%
  layout(hovermode="compare", title = "Boxplot of all prices(left) Vs. Prices of Great & V. Good Hedge opportunities(right)", showlegend = F)
subplot(box1, box2, shareY = T)



Gather some basic statistics about the PAT output

year_strips <- list(Y_14AM, Y_15, Y_15AM, Y_16, Y_16AM, Y_17, Y_17AM)
fraction <- function(strip){
  yearOrderedByPrice <- strip[order(-strip$Price),]
  first_quartile <- yearOrderedByPrice[c(1:trunc(nrow(yearOrderedByPrice)/4)),]
  second_quartile <- yearOrderedByPrice[c((trunc(nrow(yearOrderedByPrice)/4)+1):trunc(nrow(yearOrderedByPrice)/2)),]
  third_quartile <- yearOrderedByPrice[c((trunc(nrow(yearOrderedByPrice)/2)+1):trunc(nrow(yearOrderedByPrice)*3/4)),]
  fourth_quartile <- yearOrderedByPrice[c((trunc(nrow(yearOrderedByPrice)*3/4)+1):trunc(nrow(yearOrderedByPrice))),]
  
  numOfGreatInFirstQuartile <- sum(first_quartile$Recommendation == "5 - Great hedging opportunity")
  numOfVeryGoodInFirstQuartile <- sum(first_quartile$Recommendation == "4 - Very good hedging opportunity")
  numOfGreatInSecondQuartile <- sum(second_quartile$Recommendation == "5 - Great hedging opportunity")
  numOfVeryGoodInSecondQuartile <- sum(second_quartile$Recommendation == "4 - Very good hedging opportunity")
  numOfGreatInThirdQuartile <- sum(third_quartile$Recommendation == "5 - Great hedging opportunity")
  numOfVeryGoodInThirdQuartile <- sum(third_quartile$Recommendation == "4 - Very good hedging opportunity")
  numOfGreatInFourthQuartile <- sum(fourth_quartile$Recommendation == "5 - Great hedging opportunity")
  numOfVeryGoodInFourthQuartile <- sum(fourth_quartile$Recommendation == "4 - Very good hedging opportunity")
  numOfOppInFirstQuartile <- numOfGreatInFirstQuartile + numOfVeryGoodInFirstQuartile
  numOfOppInSecondQuartile <- numOfGreatInSecondQuartile + numOfVeryGoodInSecondQuartile
  numOfOppInThirdQuartile <- numOfGreatInThirdQuartile + numOfVeryGoodInThirdQuartile
  numOfOppInFourthQuartile <- numOfGreatInFourthQuartile + numOfVeryGoodInFourthQuartile
  cat("Total no. of Great or V. Good hedging opportunities for the strip",strip$Contract[1],":",numOfOppInFirstQuartile + numOfOppInSecondQuartile + numOfOppInThirdQuartile + numOfOppInFourthQuartile, "\n" )
  cat("No. of Great or V. Good hedging opportunities in the top quarter(0-25%, first quartile) prices for the strip",strip$Contract[1],":",numOfOppInFirstQuartile, "\n")
  cat("No. of Great or V. Good hedging opportunities in the next quarter(25%-50%, second quartile) prices for the strip",strip$Contract[1],":",numOfOppInSecondQuartile, "\n")
  cat("No. of Great or V. Good hedging opportunities in the next quarter(50%-75%, third quartile) prices for the strip",strip$Contract[1],":",numOfOppInThirdQuartile, "\n")
  cat("No. of Great or V. Good hedging opportunities in the bottom quarter(75%-100%, fourth quartile) prices for the strip",strip$Contract[1],":",numOfOppInFourthQuartile, "\n\n")
  
}
for(i in year_strips){
  fraction(i)
}
Total no. of Great or V. Good hedging opportunities for the strip Y_14AM : 5 
No. of Great or V. Good hedging opportunities in the top quarter(0-25%, first quartile) prices for the strip Y_14AM : 2 
No. of Great or V. Good hedging opportunities in the next quarter(25%-50%, second quartile) prices for the strip Y_14AM : 3 
No. of Great or V. Good hedging opportunities in the next quarter(50%-75%, third quartile) prices for the strip Y_14AM : 0 
No. of Great or V. Good hedging opportunities in the bottom quarter(75%-100%, fourth quartile) prices for the strip Y_14AM : 0 

Total no. of Great or V. Good hedging opportunities for the strip Y_15 : 12 
No. of Great or V. Good hedging opportunities in the top quarter(0-25%, first quartile) prices for the strip Y_15 : 0 
No. of Great or V. Good hedging opportunities in the next quarter(25%-50%, second quartile) prices for the strip Y_15 : 0 
No. of Great or V. Good hedging opportunities in the next quarter(50%-75%, third quartile) prices for the strip Y_15 : 2 
No. of Great or V. Good hedging opportunities in the bottom quarter(75%-100%, fourth quartile) prices for the strip Y_15 : 10 

Total no. of Great or V. Good hedging opportunities for the strip Y_15AM : 10 
No. of Great or V. Good hedging opportunities in the top quarter(0-25%, first quartile) prices for the strip Y_15AM : 3 
No. of Great or V. Good hedging opportunities in the next quarter(25%-50%, second quartile) prices for the strip Y_15AM : 0 
No. of Great or V. Good hedging opportunities in the next quarter(50%-75%, third quartile) prices for the strip Y_15AM : 0 
No. of Great or V. Good hedging opportunities in the bottom quarter(75%-100%, fourth quartile) prices for the strip Y_15AM : 7 

Total no. of Great or V. Good hedging opportunities for the strip Y_16 : 68 
No. of Great or V. Good hedging opportunities in the top quarter(0-25%, first quartile) prices for the strip Y_16 : 7 
No. of Great or V. Good hedging opportunities in the next quarter(25%-50%, second quartile) prices for the strip Y_16 : 29 
No. of Great or V. Good hedging opportunities in the next quarter(50%-75%, third quartile) prices for the strip Y_16 : 6 
No. of Great or V. Good hedging opportunities in the bottom quarter(75%-100%, fourth quartile) prices for the strip Y_16 : 26 

Total no. of Great or V. Good hedging opportunities for the strip Y_16AM : 66 
No. of Great or V. Good hedging opportunities in the top quarter(0-25%, first quartile) prices for the strip Y_16AM : 5 
No. of Great or V. Good hedging opportunities in the next quarter(25%-50%, second quartile) prices for the strip Y_16AM : 28 
No. of Great or V. Good hedging opportunities in the next quarter(50%-75%, third quartile) prices for the strip Y_16AM : 19 
No. of Great or V. Good hedging opportunities in the bottom quarter(75%-100%, fourth quartile) prices for the strip Y_16AM : 14 

Total no. of Great or V. Good hedging opportunities for the strip Y_17 : 47 
No. of Great or V. Good hedging opportunities in the top quarter(0-25%, first quartile) prices for the strip Y_17 : 11 
No. of Great or V. Good hedging opportunities in the next quarter(25%-50%, second quartile) prices for the strip Y_17 : 12 
No. of Great or V. Good hedging opportunities in the next quarter(50%-75%, third quartile) prices for the strip Y_17 : 3 
No. of Great or V. Good hedging opportunities in the bottom quarter(75%-100%, fourth quartile) prices for the strip Y_17 : 21 

Total no. of Great or V. Good hedging opportunities for the strip Y_17AM : 69 
No. of Great or V. Good hedging opportunities in the top quarter(0-25%, first quartile) prices for the strip Y_17AM : 20 
No. of Great or V. Good hedging opportunities in the next quarter(25%-50%, second quartile) prices for the strip Y_17AM : 9 
No. of Great or V. Good hedging opportunities in the next quarter(50%-75%, third quartile) prices for the strip Y_17AM : 8 
No. of Great or V. Good hedging opportunities in the bottom quarter(75%-100%, fourth quartile) prices for the strip Y_17AM : 32 



Evaluating PAT

To evaluate PAT more realistically we calculate weighted average prices by incorporating delays in client response time. We use two approaches to calculate the weighted averages:

1) Averaged all at once: Number of client responses for each date are summed together and divided by total number of client responses.

\[ Average\,client\,responses\,on\,\,k^{th}\,\,day\,=\,\frac{\sum(Client\,responses\,on\,k^{th}\,day\,for\,each\,date)}{\sum(Number\,of\,client\,responses\,for\,each\,date)} \]

allStripsPricelist <- list()
for(year in year_strips){
  opportunity_dates <- with(year, Date[year$Recommendation == "5 - Great hedging opportunity" | year$Recommendation == "4 - Very good hedging opportunity"])
  allpricelist <- list()
  for(i in opportunity_dates){
    #print(as.character(as.Date(as.POSIXct(i, origin="1970-01-01"))))
    #print(Y_14AM[Y_14AM$Date==i, "Price"])
    opportunity_index <- which(year$Date == i)
    opportunity_price <- year[opportunity_index, "Price"]
    if(opportunity_index+nrow(client_responses) < (nrow(year)+1)){
      pricelist <- list(year[opportunity_index:(opportunity_index+nrow(client_responses)-1), "Price"])
      names(pricelist) <- as.character(as.Date(as.POSIXct(i, origin="1970-01-01")))
    }
    else{
      pricelist <- list(year[opportunity_index:nrow(year), "Price"])
      names(pricelist) <- as.character(as.Date(as.POSIXct(i, origin="1970-01-01")))
    }
    allpricelist <- append(allpricelist, pricelist)
  }
  allStripsPricelist <- append(allStripsPricelist, allpricelist)
}
avg_client_responses <- list(rowMeans(client_responses))
averaged_prices <- list()
for(i in 1:length(allStripsPricelist)){
  frac <- list((c(avg_client_responses[[1]][1:length(allStripsPricelist[[i]])]))/sum(c(avg_client_responses[[1]][1:length(allStripsPricelist[[i]])])))
  averaged_prices <- append(averaged_prices, frac)
}
fraction_prices <- Map('*', averaged_prices, allStripsPricelist)
averaged_prices <- list()
for(i in 1:length(fraction_prices)){
  averaged_prices <- append(averaged_prices, sum(fraction_prices[[i]]))
}
averaged_prices <- c(sapply(averaged_prices, '[', i=1))
contractndates <- list(Date=pat_output[pat_output$Recommendation=="5 - Great hedging opportunity" | pat_output$Recommendation=="4 - Very good hedging opportunity", "Date"], Contract=pat_output[pat_output$Recommendation=="5 - Great hedging opportunity" | pat_output$Recommendation=="4 - Very good hedging opportunity", "Contract"])
dates <- contractndates$Date
contracts <- contractndates$Contract
averaged_prices <- data.frame(Contract=contracts, Date=dates, Price=averaged_prices)
pat_output_modified <- pat_output
pat_mod_index <- which(outer(pat_output_modified$Contract, averaged_prices$Contract, "==")                      & outer(pat_output_modified$Date, averaged_prices$Date, "=="),
                       arr.ind = TRUE)
for (idx in 1:nrow(pat_mod_index)){
  pat_output_modified$Price[pat_mod_index[idx,"row"]] <- averaged_prices$Price[idx]
}
pat_output_modified <- pat_output_modified[order(pat_output_modified$Contract), ]
modified_Y_14AM <- pat_output_modified[pat_output_modified$Contract=="Y_14AM",]
modified_Y_15 <- pat_output_modified[pat_output_modified$Contract=="Y_15",]
modified_Y_15AM <- pat_output_modified[pat_output_modified$Contract=="Y_15AM",]
modified_Y_16 <- pat_output_modified[pat_output_modified$Contract=="Y_16",]
modified_Y_16AM <- pat_output_modified[pat_output_modified$Contract=="Y_16AM",]
modified_Y_17 <- pat_output_modified[pat_output_modified$Contract=="Y_17",]
modified_Y_17AM <- pat_output_modified[pat_output_modified$Contract=="Y_17AM",]



Violin plots showing weighted average prices for Great & V. Good hedging opportunities taking future 28 days as client responses/ delays into consideration. A red dot represents “5 - Great hedging opportunity” and a yellow dot represents “4 - Very good hedging opportunity”. Horizontal crossbar(black) shows the median price for that strip.

ggplot(width = 950, pat_output_modified, aes(Contract, Price)) + geom_violin(aes(fill = Contract)) + scale_fill_manual(values=c("#B4E0D2", "#FCC6B3", "#C6CFE4", "#F2C5E0", "#D3EAAD", "#FEEBA1", "#F1E1CA")) + geom_point(data=pat_output[pat_output$Recommendation=="5 - Great hedging opportunity",], aes(Contract, Price), color = "#B40619", position = position_jitter(0.09), size = 0.5) + geom_point(data=pat_output[pat_output$Recommendation=="4 - Very good hedging opportunity",], aes(Contract, Price), color = "#E56621", position = position_jitter(0.09), size = 0.5) + stat_summary(fun.y = "median", fun.ymin ="median", fun.ymax ="median", geom ="crossbar", width=0.2, fatten = 1)

The plot doesn’t look very different from previous the violin plot or the changes are insignificant to be visible at high level.



Basic statistics with weighted prices for Great & V. Good hedging Prices.

year_strips <- list(modified_Y_14AM, modified_Y_15, modified_Y_15AM, modified_Y_16, modified_Y_16AM, modified_Y_17, modified_Y_17AM)
fraction <- function(strip){
  yearOrderedByPrice <- strip[order(-strip$Price),]
  first_quartile <- yearOrderedByPrice[c(1:trunc(nrow(yearOrderedByPrice)/4)),]
  second_quartile <- yearOrderedByPrice[c((trunc(nrow(yearOrderedByPrice)/4)+1):trunc(nrow(yearOrderedByPrice)/2)),]
  third_quartile <- yearOrderedByPrice[c((trunc(nrow(yearOrderedByPrice)/2)+1):trunc(nrow(yearOrderedByPrice)*3/4)),]
  fourth_quartile <- yearOrderedByPrice[c((trunc(nrow(yearOrderedByPrice)*3/4)+1):trunc(nrow(yearOrderedByPrice))),]
  
  numOfGreatInFirstQuartile <- sum(first_quartile$Recommendation == "5 - Great hedging opportunity")
  numOfVeryGoodInFirstQuartile <- sum(first_quartile$Recommendation == "4 - Very good hedging opportunity")
  numOfGreatInSecondQuartile <- sum(second_quartile$Recommendation == "5 - Great hedging opportunity")
  numOfVeryGoodInSecondQuartile <- sum(second_quartile$Recommendation == "4 - Very good hedging opportunity")
  numOfGreatInThirdQuartile <- sum(third_quartile$Recommendation == "5 - Great hedging opportunity")
  numOfVeryGoodInThirdQuartile <- sum(third_quartile$Recommendation == "4 - Very good hedging opportunity")
  numOfGreatInFourthQuartile <- sum(fourth_quartile$Recommendation == "5 - Great hedging opportunity")
  numOfVeryGoodInFourthQuartile <- sum(fourth_quartile$Recommendation == "4 - Very good hedging opportunity")
  numOfOppInFirstQuartile <- numOfGreatInFirstQuartile + numOfVeryGoodInFirstQuartile
  numOfOppInSecondQuartile <- numOfGreatInSecondQuartile + numOfVeryGoodInSecondQuartile
  numOfOppInThirdQuartile <- numOfGreatInThirdQuartile + numOfVeryGoodInThirdQuartile
  numOfOppInFourthQuartile <- numOfGreatInFourthQuartile + numOfVeryGoodInFourthQuartile
  cat("Total no. of Great or V. Good hedging opportunities for the strip",strip$Contract[1],":",numOfOppInFirstQuartile + numOfOppInSecondQuartile + numOfOppInThirdQuartile + numOfOppInFourthQuartile, "\n" )
  cat("No. of Great or V. Good hedging opportunities in the top quarter(0-25%, first quartile) prices for the strip",strip$Contract[1],":",numOfOppInFirstQuartile, "\n")
  cat("No. of Great or V. Good hedging opportunities in the next quarter(25%-50%, second quartile) prices for the strip",strip$Contract[1],":",numOfOppInSecondQuartile, "\n")
  cat("No. of Great or V. Good hedging opportunities in the next quarter(50%-75%, third quartile) prices for the strip",strip$Contract[1],":",numOfOppInThirdQuartile, "\n")
  cat("No. of Great or V. Good hedging opportunities in the bottom quarter(75%-100%, fourth quartile) prices for the strip",strip$Contract[1],":",numOfOppInFourthQuartile, "\n\n")
  
}
for(i in year_strips){
  fraction(i)
}
Total no. of Great or V. Good hedging opportunities for the strip Y_14AM : 5 
No. of Great or V. Good hedging opportunities in the top quarter(0-25%, first quartile) prices for the strip Y_14AM : 2 
No. of Great or V. Good hedging opportunities in the next quarter(25%-50%, second quartile) prices for the strip Y_14AM : 3 
No. of Great or V. Good hedging opportunities in the next quarter(50%-75%, third quartile) prices for the strip Y_14AM : 0 
No. of Great or V. Good hedging opportunities in the bottom quarter(75%-100%, fourth quartile) prices for the strip Y_14AM : 0 

Total no. of Great or V. Good hedging opportunities for the strip Y_15 : 12 
No. of Great or V. Good hedging opportunities in the top quarter(0-25%, first quartile) prices for the strip Y_15 : 0 
No. of Great or V. Good hedging opportunities in the next quarter(25%-50%, second quartile) prices for the strip Y_15 : 0 
No. of Great or V. Good hedging opportunities in the next quarter(50%-75%, third quartile) prices for the strip Y_15 : 5 
No. of Great or V. Good hedging opportunities in the bottom quarter(75%-100%, fourth quartile) prices for the strip Y_15 : 7 

Total no. of Great or V. Good hedging opportunities for the strip Y_15AM : 10 
No. of Great or V. Good hedging opportunities in the top quarter(0-25%, first quartile) prices for the strip Y_15AM : 3 
No. of Great or V. Good hedging opportunities in the next quarter(25%-50%, second quartile) prices for the strip Y_15AM : 0 
No. of Great or V. Good hedging opportunities in the next quarter(50%-75%, third quartile) prices for the strip Y_15AM : 0 
No. of Great or V. Good hedging opportunities in the bottom quarter(75%-100%, fourth quartile) prices for the strip Y_15AM : 7 

Total no. of Great or V. Good hedging opportunities for the strip Y_16 : 68 
No. of Great or V. Good hedging opportunities in the top quarter(0-25%, first quartile) prices for the strip Y_16 : 7 
No. of Great or V. Good hedging opportunities in the next quarter(25%-50%, second quartile) prices for the strip Y_16 : 29 
No. of Great or V. Good hedging opportunities in the next quarter(50%-75%, third quartile) prices for the strip Y_16 : 6 
No. of Great or V. Good hedging opportunities in the bottom quarter(75%-100%, fourth quartile) prices for the strip Y_16 : 26 

Total no. of Great or V. Good hedging opportunities for the strip Y_16AM : 66 
No. of Great or V. Good hedging opportunities in the top quarter(0-25%, first quartile) prices for the strip Y_16AM : 2 
No. of Great or V. Good hedging opportunities in the next quarter(25%-50%, second quartile) prices for the strip Y_16AM : 34 
No. of Great or V. Good hedging opportunities in the next quarter(50%-75%, third quartile) prices for the strip Y_16AM : 16 
No. of Great or V. Good hedging opportunities in the bottom quarter(75%-100%, fourth quartile) prices for the strip Y_16AM : 14 

Total no. of Great or V. Good hedging opportunities for the strip Y_17 : 47 
No. of Great or V. Good hedging opportunities in the top quarter(0-25%, first quartile) prices for the strip Y_17 : 10 
No. of Great or V. Good hedging opportunities in the next quarter(25%-50%, second quartile) prices for the strip Y_17 : 13 
No. of Great or V. Good hedging opportunities in the next quarter(50%-75%, third quartile) prices for the strip Y_17 : 6 
No. of Great or V. Good hedging opportunities in the bottom quarter(75%-100%, fourth quartile) prices for the strip Y_17 : 18 

Total no. of Great or V. Good hedging opportunities for the strip Y_17AM : 69 
No. of Great or V. Good hedging opportunities in the top quarter(0-25%, first quartile) prices for the strip Y_17AM : 20 
No. of Great or V. Good hedging opportunities in the next quarter(25%-50%, second quartile) prices for the strip Y_17AM : 11 
No. of Great or V. Good hedging opportunities in the next quarter(50%-75%, third quartile) prices for the strip Y_17AM : 8 
No. of Great or V. Good hedging opportunities in the bottom quarter(75%-100%, fourth quartile) prices for the strip Y_17AM : 30 



Relative bar plot showing the difference between weighted average prices for hedging opportunities Vs. actual prices on the day of Great or V. Good hedging opportunities.

modified_opp <- pat_output_modified[pat_output_modified$Recommendation=="5 - Great hedging opportunity" | pat_output_modified$Recommendation=="4 - Very good hedging opportunity", "Price"]
opp <- pat_output[pat_output$Recommendation=="5 - Great hedging opportunity" |
                    pat_output$Recommendation=="4 - Very good hedging opportunity", "Price"]
x <- pat_output[pat_output$Recommendation=="5 - Great hedging opportunity" | pat_output$Recommendation=="4 - Very good hedging opportunity", "Date"]
y <- unlist(Map('-', modified_opp, opp))
data <- data.frame(x, y)
plot_ly(data, x = ~x, y = ~y, type = 'bar', width = 950) %>% layout(hovermode="compare", 
         title = 'Overview of modified effective hedging opportunity prices',
         xaxis = list(title = 'Dates'),
         yaxis = list(title = 'Difference(effective - actual)'))



lower_prices <- sum(y<0)
higher_prices <- sum(y>0)
unchanged_prices <- sum(y==0)
percent_lower_price <- 100*lower_prices/nrow(averaged_prices)
percent_higher_price <- 100*higher_prices/nrow(averaged_prices)
percent_same_price <- 100*unchanged_prices/nrow(averaged_prices)
cat("Weighted average great & very good hedging opportunity prices that are lower than the actual prices",percent_lower_price,"%\nWeighted average great & very good hedging opportunity prices that are higher than the actual prices", percent_higher_price, "%\nWeighted average great & very good hedging opportunity prices that are same as the actual prices",percent_same_price,"%\n\n")
Weighted average great & very good hedging opportunity prices that are lower than the actual prices 43.68231 %
Weighted average great & very good hedging opportunity prices that are higher than the actual prices 55.59567 %
Weighted average great & very good hedging opportunity prices that are same as the actual prices 0.7220217 %



Relative bar plot showing the difference between weighted average prices for hedging opportunities Vs. actual prices on the day of Great or V. Good hedging opportunities for each strip.

modified_opp_Y_14AM <- modified_Y_14AM[modified_Y_14AM$Recommendation=="5 - Great hedging opportunity" | modified_Y_14AM$Recommendation=="4 - Very good hedging opportunity", "Price"]
opp_Y_14AM <- Y_14AM[Y_14AM$Recommendation=="5 - Great hedging opportunity" |
                    Y_14AM$Recommendation=="4 - Very good hedging opportunity", "Price"]
x_Y_14AM <- modified_Y_14AM[modified_Y_14AM$Recommendation=="5 - Great hedging opportunity" | modified_Y_14AM$Recommendation=="4 - Very good hedging opportunity", "Date"]
y_Y_14AM <- unlist(Map('-', modified_opp_Y_14AM, opp_Y_14AM))
data_Y_14AM <- data.frame(x_Y_14AM, y_Y_14AM)
p1 <- plot_ly(data, x = ~x_Y_14AM, y = ~y_Y_14AM, type = 'bar', name = 'Y_14AM', width = 950, height = 650) %>% layout(hovermode="compare", xaxis = list(title = 'Dates'), yaxis = list(title = 'Difference'))
modified_opp_Y_15 <- modified_Y_15[modified_Y_15$Recommendation=="5 - Great hedging opportunity" | modified_Y_15$Recommendation=="4 - Very good hedging opportunity", "Price"]
opp_Y_15 <- Y_15[Y_15$Recommendation=="5 - Great hedging opportunity" |
                    Y_15$Recommendation=="4 - Very good hedging opportunity", "Price"]
x_Y_15 <- modified_Y_15[modified_Y_15$Recommendation=="5 - Great hedging opportunity" | modified_Y_15$Recommendation=="4 - Very good hedging opportunity", "Date"]
y_Y_15 <- unlist(Map('-', modified_opp_Y_15, opp_Y_15))
data_Y_15 <- data.frame(x_Y_15, y_Y_15)
p2 <- plot_ly(data, x = ~x_Y_15, y = ~y_Y_15, type = 'bar', name = 'Y_15', width = 950) %>% layout(hovermode="compare", 
         xaxis = list(title = 'Dates'),
         yaxis = list(title = 'Difference'))
modified_opp_Y_15AM <- modified_Y_15AM[modified_Y_15AM$Recommendation=="5 - Great hedging opportunity" | modified_Y_15AM$Recommendation=="4 - Very good hedging opportunity", "Price"]
opp_Y_15AM <- Y_15AM[Y_15AM$Recommendation=="5 - Great hedging opportunity" |
                    Y_15AM$Recommendation=="4 - Very good hedging opportunity", "Price"]
x_Y_15AM <- modified_Y_15AM[modified_Y_15AM$Recommendation=="5 - Great hedging opportunity" | modified_Y_15AM$Recommendation=="4 - Very good hedging opportunity", "Date"]
y_Y_15AM <- unlist(Map('-', modified_opp_Y_15AM, opp_Y_15AM))
data_Y_15AM <- data.frame(x_Y_15AM, y_Y_15AM)
p3 <- plot_ly(data, x = ~x_Y_15AM, y = ~y_Y_15AM, type = 'bar', name = 'Y_15AM', width = 950) %>% layout(hovermode="compare", 
         xaxis = list(title = 'Dates'),
         yaxis = list(title = 'Difference'))
modified_opp_Y_16 <- modified_Y_16[modified_Y_16$Recommendation=="5 - Great hedging opportunity" | modified_Y_16$Recommendation=="4 - Very good hedging opportunity", "Price"]
opp_Y_16 <- Y_16[Y_16$Recommendation=="5 - Great hedging opportunity" |
                    Y_16$Recommendation=="4 - Very good hedging opportunity", "Price"]
x_Y_16 <- modified_Y_16[modified_Y_16$Recommendation=="5 - Great hedging opportunity" | modified_Y_16$Recommendation=="4 - Very good hedging opportunity", "Date"]
y_Y_16 <- unlist(Map('-', modified_opp_Y_16, opp_Y_16))
data_Y_16 <- data.frame(x_Y_16, y_Y_16)
p4 <- plot_ly(data, x = ~x_Y_16, y = ~y_Y_16, type = 'bar', name = 'Y_16', width = 950) %>% layout(hovermode="compare", 
         xaxis = list(title = 'Dates'),
         yaxis = list(title = 'Difference'))
modified_opp_Y_16AM <- modified_Y_16AM[modified_Y_16AM$Recommendation=="5 - Great hedging opportunity" | modified_Y_16AM$Recommendation=="4 - Very good hedging opportunity", "Price"]
opp_Y_16AM <- Y_16AM[Y_16AM$Recommendation=="5 - Great hedging opportunity" |
                    Y_16AM$Recommendation=="4 - Very good hedging opportunity", "Price"]
x_Y_16AM <- modified_Y_16AM[modified_Y_16AM$Recommendation=="5 - Great hedging opportunity" | modified_Y_16AM$Recommendation=="4 - Very good hedging opportunity", "Date"]
y_Y_16AM <- unlist(Map('-', modified_opp_Y_16AM, opp_Y_16AM))
data_Y_16AM <- data.frame(x_Y_16AM, y_Y_16AM)
p5 <- plot_ly(data, x = ~x_Y_16AM, y = ~y_Y_16AM, type = 'bar', name = 'Y_16AM', width = 950) %>% layout(hovermode="compare", 
         xaxis = list(title = 'Dates'),
         yaxis = list(title = 'Difference'))
modified_opp_Y_17 <- modified_Y_17[modified_Y_17$Recommendation=="5 - Great hedging opportunity" | modified_Y_17$Recommendation=="4 - Very good hedging opportunity", "Price"]
opp_Y_17 <- Y_17[Y_17$Recommendation=="5 - Great hedging opportunity" |
                    Y_17$Recommendation=="4 - Very good hedging opportunity", "Price"]
x_Y_17 <- modified_Y_17[modified_Y_17$Recommendation=="5 - Great hedging opportunity" | modified_Y_17$Recommendation=="4 - Very good hedging opportunity", "Date"]
y_Y_17 <- unlist(Map('-', modified_opp_Y_17, opp_Y_17))
data_Y_17 <- data.frame(x_Y_17, y_Y_17)
p6 <- plot_ly(data, x = ~x_Y_17, y = ~y_Y_17, type = 'bar', name = 'Y_17', width = 950) %>% layout(hovermode="compare", 
         xaxis = list(title = 'Dates'),
         yaxis = list(title = 'Difference'))
modified_opp_Y_17AM <- modified_Y_17AM[modified_Y_17AM$Recommendation=="5 - Great hedging opportunity" | modified_Y_17AM$Recommendation=="4 - Very good hedging opportunity", "Price"]
opp_Y_17AM <- Y_17AM[Y_17AM$Recommendation=="5 - Great hedging opportunity" |
                    Y_17AM$Recommendation=="4 - Very good hedging opportunity", "Price"]
x_Y_17AM <- modified_Y_17AM[modified_Y_17AM$Recommendation=="5 - Great hedging opportunity" | modified_Y_17AM$Recommendation=="4 - Very good hedging opportunity", "Date"]
y_Y_17AM <- unlist(Map('-', modified_opp_Y_17AM, opp_Y_17AM))
data_Y_17AM <- data.frame(x_Y_17AM, y_Y_17AM)
p7 <- plot_ly(data, x = ~x_Y_17AM, y = ~y_Y_17AM, type = 'bar', name = 'Y_17AM', width = 950) %>% layout(hovermode="compare", 
         xaxis = list(title = 'Dates'),
         yaxis = list(title = 'Difference'))
subplot(p1, p2, p3, p4, p5, p6, p7, nrows = 4, shareY = TRUE)



lower_prices_Y_14AM <- sum(y_Y_14AM<0)
higher_prices_Y_14AM <- sum(y_Y_14AM>0)
unchanged_prices_Y_14AM <- sum(y_Y_14AM==0)
percent_lower_price_Y_14AM <- 100*lower_prices_Y_14AM/length(Y_14AM[Y_14AM$Recommendation=="5 - Great hedging opportunity" | Y_14AM$Recommendation=="4 - Very good hedging opportunity", "Price"])
percent_higher_price_Y_14AM <- 100*higher_prices_Y_14AM/length(Y_14AM[Y_14AM$Recommendation=="5 - Great hedging opportunity" | Y_14AM$Recommendation=="4 - Very good hedging opportunity", "Price"])
percent_same_price_Y_14AM <- 100*unchanged_prices_Y_14AM/length(Y_14AM[Y_14AM$Recommendation=="5 - Great hedging opportunity" | Y_14AM$Recommendation=="4 - Very good hedging opportunity", "Price"])
cat("For the strip Y_14AM weighted average great & very good hedging opportunity prices that are lower than the actual prices",percent_lower_price_Y_14AM,"%\nFor the strip Y_14AM weighted average great & very good hedging opportunity prices that are higher than the actual prices", percent_higher_price_Y_14AM, "%\nFor the strip Y_14AM weighted average great & very good hedging opportunity prices that are same as the actual prices",percent_same_price_Y_14AM,"%\n\n")
For the strip Y_14AM weighted average great & very good hedging opportunity prices that are lower than the actual prices 20 %
For the strip Y_14AM weighted average great & very good hedging opportunity prices that are higher than the actual prices 60 %
For the strip Y_14AM weighted average great & very good hedging opportunity prices that are same as the actual prices 20 %
lower_prices_Y_15 <- sum(y_Y_15<0)
higher_prices_Y_15 <- sum(y_Y_15>0)
unchanged_prices_Y_15 <- sum(y_Y_15==0)
percent_lower_price_Y_15 <- 100*lower_prices_Y_15/length(Y_15[Y_15$Recommendation=="5 - Great hedging opportunity" | Y_15$Recommendation=="4 - Very good hedging opportunity", "Price"])
percent_higher_price_Y_15 <- 100*higher_prices_Y_15/length(Y_15[Y_15$Recommendation=="5 - Great hedging opportunity" | Y_15$Recommendation=="4 - Very good hedging opportunity", "Price"])
percent_same_price_Y_15 <- 100*unchanged_prices_Y_15/length(Y_15[Y_15$Recommendation=="5 - Great hedging opportunity" | Y_15$Recommendation=="4 - Very good hedging opportunity", "Price"])
cat("For the strip Y_15 weighted average great & very good hedging opportunity prices that are lower than the actual prices",percent_lower_price_Y_15,"%\nFor the strip Y_15 weighted average great & very good hedging opportunity prices that are higher than the actual prices", percent_higher_price_Y_15, "%\nFor the strip Y_15 weighted average great & very good hedging opportunity prices that are same as the actual prices",percent_same_price_Y_15,"%\n\n")
For the strip Y_15 weighted average great & very good hedging opportunity prices that are lower than the actual prices 8.333333 %
For the strip Y_15 weighted average great & very good hedging opportunity prices that are higher than the actual prices 83.33333 %
For the strip Y_15 weighted average great & very good hedging opportunity prices that are same as the actual prices 8.333333 %
lower_prices_Y_15AM <- sum(y_Y_15AM<0)
higher_prices_Y_15AM <- sum(y_Y_15AM>0)
unchanged_prices_Y_15AM <- sum(y_Y_15AM==0)
percent_lower_price_Y_15AM <- 100*lower_prices_Y_15AM/length(Y_15AM[Y_15AM$Recommendation=="5 - Great hedging opportunity" | Y_15AM$Recommendation=="4 - Very good hedging opportunity", "Price"])
percent_higher_price_Y_15AM <- 100*higher_prices_Y_15AM/length(Y_15AM[Y_15AM$Recommendation=="5 - Great hedging opportunity" | Y_15AM$Recommendation=="4 - Very good hedging opportunity", "Price"])
percent_same_price_Y_15AM <- 100*unchanged_prices_Y_15AM/length(Y_15AM[Y_15AM$Recommendation=="5 - Great hedging opportunity" | Y_15AM$Recommendation=="4 - Very good hedging opportunity", "Price"])
cat("For the strip Y_15AM weighted average great & very good hedging opportunity prices that are lower than the actual prices",percent_lower_price_Y_15AM,"%\nFor the strip Y_15AM weighted average great & very good hedging opportunity prices that are higher than the actual prices", percent_higher_price_Y_15AM, "%\nFor the strip Y_15AM weighted average great & very good hedging opportunity prices that are same as the actual prices",percent_same_price_Y_15AM,"%\n\n")
For the strip Y_15AM weighted average great & very good hedging opportunity prices that are lower than the actual prices 30 %
For the strip Y_15AM weighted average great & very good hedging opportunity prices that are higher than the actual prices 70 %
For the strip Y_15AM weighted average great & very good hedging opportunity prices that are same as the actual prices 0 %
lower_prices_Y_16 <- sum(y_Y_16<0)
higher_prices_Y_16 <- sum(y_Y_16>0)
unchanged_prices_Y_16 <- sum(y_Y_16==0)
percent_lower_price_Y_16 <- 100*lower_prices_Y_16/length(Y_16[Y_16$Recommendation=="5 - Great hedging opportunity" | Y_16$Recommendation=="4 - Very good hedging opportunity", "Price"])
percent_higher_price_Y_16 <- 100*higher_prices_Y_16/length(Y_16[Y_16$Recommendation=="5 - Great hedging opportunity" | Y_16$Recommendation=="4 - Very good hedging opportunity", "Price"])
percent_same_price_Y_16 <- 100*unchanged_prices_Y_16/length(Y_16[Y_16$Recommendation=="5 - Great hedging opportunity" | Y_16$Recommendation=="4 - Very good hedging opportunity", "Price"])
cat("For the strip Y_16 weighted average great & very good hedging opportunity prices that are lower than the actual prices",percent_lower_price_Y_16,"%\nFor the strip Y_16 weighted average great & very good hedging opportunity prices that are higher than the actual prices", percent_higher_price_Y_16, "%\nFor the strip Y_16 weighted average great & very good hedging opportunity prices that are same as the actual prices",percent_same_price_Y_16,"%\n\n")
For the strip Y_16 weighted average great & very good hedging opportunity prices that are lower than the actual prices 70.58824 %
For the strip Y_16 weighted average great & very good hedging opportunity prices that are higher than the actual prices 29.41176 %
For the strip Y_16 weighted average great & very good hedging opportunity prices that are same as the actual prices 0 %
lower_prices_Y_16AM <- sum(y_Y_16AM<0)
higher_prices_Y_16AM <- sum(y_Y_16AM>0)
unchanged_prices_Y_16AM <- sum(y_Y_16AM==0)
percent_lower_price_Y_16AM <- 100*lower_prices_Y_16AM/length(Y_16AM[Y_16AM$Recommendation=="5 - Great hedging opportunity" | Y_16AM$Recommendation=="4 - Very good hedging opportunity", "Price"])
percent_higher_price_Y_16AM <- 100*higher_prices_Y_16AM/length(Y_16AM[Y_16AM$Recommendation=="5 - Great hedging opportunity" | Y_16AM$Recommendation=="4 - Very good hedging opportunity", "Price"])
percent_same_price_Y_16AM <- 100*unchanged_prices_Y_16AM/length(Y_16AM[Y_16AM$Recommendation=="5 - Great hedging opportunity" | Y_16AM$Recommendation=="4 - Very good hedging opportunity", "Price"])
cat("For the strip Y_16AM weighted average great & very good hedging opportunity prices that are lower than the actual prices",percent_lower_price_Y_16AM,"%\nFor the strip Y_16AM weighted average great & very good hedging opportunity prices that are higher than the actual prices", percent_higher_price_Y_16AM, "%\nFor the strip Y_16AM weighted average great & very good hedging opportunity prices that are same as the actual prices",percent_same_price_Y_16AM,"%\n\n")
For the strip Y_16AM weighted average great & very good hedging opportunity prices that are lower than the actual prices 42.42424 %
For the strip Y_16AM weighted average great & very good hedging opportunity prices that are higher than the actual prices 57.57576 %
For the strip Y_16AM weighted average great & very good hedging opportunity prices that are same as the actual prices 0 %
lower_prices_Y_17 <- sum(y_Y_17<0)
higher_prices_Y_17 <- sum(y_Y_17>0)
unchanged_prices_Y_17 <- sum(y_Y_17==0)
percent_lower_price_Y_17 <- 100*lower_prices_Y_17/length(Y_17[Y_17$Recommendation=="5 - Great hedging opportunity" | Y_17$Recommendation=="4 - Very good hedging opportunity", "Price"])
percent_higher_price_Y_17 <- 100*higher_prices_Y_17/length(Y_17[Y_17$Recommendation=="5 - Great hedging opportunity" | Y_17$Recommendation=="4 - Very good hedging opportunity", "Price"])
percent_same_price_Y_17 <- 100*unchanged_prices_Y_17/length(Y_17[Y_17$Recommendation=="5 - Great hedging opportunity" | Y_17$Recommendation=="4 - Very good hedging opportunity", "Price"])
cat("For the strip Y_17 weighted average great & very good hedging opportunity prices that are lower than the actual prices",percent_lower_price_Y_17,"%\nFor the strip Y_17 weighted average great & very good hedging opportunity prices that are higher than the actual prices", percent_higher_price_Y_17, "%\nFor the strip Y_17 weighted average great & very good hedging opportunity prices that are same as the actual prices",percent_same_price_Y_17,"%\n\n")
For the strip Y_17 weighted average great & very good hedging opportunity prices that are lower than the actual prices 40.42553 %
For the strip Y_17 weighted average great & very good hedging opportunity prices that are higher than the actual prices 59.57447 %
For the strip Y_17 weighted average great & very good hedging opportunity prices that are same as the actual prices 0 %
lower_prices_Y_17AM <- sum(y_Y_17AM<0)
higher_prices_Y_17AM <- sum(y_Y_17AM>0)
unchanged_prices_Y_17AM <- sum(y_Y_17AM==0)
percent_lower_price_Y_17AM <- 100*lower_prices_Y_17AM/length(Y_17AM[Y_17AM$Recommendation=="5 - Great hedging opportunity" | Y_17AM$Recommendation=="4 - Very good hedging opportunity", "Price"])
percent_higher_price_Y_17AM <- 100*higher_prices_Y_17AM/length(Y_17AM[Y_17AM$Recommendation=="5 - Great hedging opportunity" | Y_17AM$Recommendation=="4 - Very good hedging opportunity", "Price"])
percent_same_price_Y_17AM <- 100*unchanged_prices_Y_17AM/length(Y_17AM[Y_17AM$Recommendation=="5 - Great hedging opportunity" | Y_17AM$Recommendation=="4 - Very good hedging opportunity", "Price"])
cat("For the strip Y_17AM weighted average great & very good hedging opportunity prices that are lower than the actual prices",percent_lower_price_Y_17AM,"%\nFor the strip Y_17AM weighted average great & very good hedging opportunity prices that are higher than the actual prices", percent_higher_price_Y_17AM, "%\nFor the strip Y_17AM weighted average great & very good hedging opportunity prices that are same as the actual prices",percent_same_price_Y_17AM,"%\n\n")
For the strip Y_17AM weighted average great & very good hedging opportunity prices that are lower than the actual prices 30.43478 %
For the strip Y_17AM weighted average great & very good hedging opportunity prices that are higher than the actual prices 69.56522 %
For the strip Y_17AM weighted average great & very good hedging opportunity prices that are same as the actual prices 0 %

2) Averaged over average of each year: Number of client responses for each date of a particular year are averaged to get an yearly average which are then summed together and divided by total number of client responses averaged over each year.

\[ Average\,client\,responses\,on\,\,k^{th}\,\,day\,= \frac{\sum(Year\,average\,client\,responses\,on\,k^{th}\,day)}{\sum(Number\,of\,average\,client\, responses\, for\, each\, year)} \]

Since there isn’t much of a difference in the averaged outputs from both approaches, we used only the \(1^{st}\) approach.



Are the differences between the effective averaged prices and actual prices really significant?

To evaluate the significance we do a significance test with

LS0tCnRpdGxlOiAiUHJlZGljdGl2ZSBBbmFseXRpY3MgVG9vbChQQVQpIEV2YWx1YXRpb24iCm91dHB1dDoKICBodG1sX25vdGVib29rOiBkZWZhdWx0CiAgaHRtbF9kb2N1bWVudDogZGVmYXVsdAotLS0KClRoaXMgaXMgYW4gW1IgTWFya2Rvd25dKGh0dHA6Ly9ybWFya2Rvd24ucnN0dWRpby5jb20pIE5vdGVib29rIHRoYXQgZGVzY3JpYmVzIHRoZSB0ZWNobmlxdWVzIGZvciBldmFsdWF0aW5nIHRoZSBQcmVkaWN0aXZlIEFuYWx5dGljcyBUb29sIGFuZCB0aGVpciByZXN1bHRzLiBUaGUgcmVzdWx0cyBmcm9tIHRoZSBleGVjdXRlZCBjb2RlIGFwcGVhciBiZW5lYXRoIHRoZSBjb2RlIGl0c2VsZi4gICAgCgojIyMjI0luc3RhbGxpbmcgcmVxdWlyZWQgbGlicmFyaWVzOiAgCgojIyMjIyNyZWFkeGwsIHBsb3RseSBhbmQgZ2dwbG90MgpgYGB7cn0Kb3B0aW9ucyh3YXJuPS0xKQpyZXF1aXJlKHJlYWR4bCkKcmVxdWlyZShwbG90bHkpCnJlcXVpcmUoZ2dwbG90MikKc2V0LnNlZWQoODI3NCkKYGBgCiAgCiAgCjxicj48YnI+CgojIyMjI0ltcG9ydGluZyBkYXRhIGZvciBhbmFseXNpczoKCiMjIyMjI1tQcmljZXNdKGh0dHBzOi8vZG9jcy5nb29nbGUuY29tL3NwcmVhZHNoZWV0cy9kLzE3N2o3ODM5T3BobGl3SEdBWk5sMFM5aFZxOTNTckdNM0NvVDJwS3VhU0UwL2VkaXQ/dXNwPXNoYXJpbmcpLCBbUEFUIG91dHB1dF0oaHR0cHM6Ly9kb2NzLmdvb2dsZS5jb20vc3ByZWFkc2hlZXRzL2QvMV84NllkTno5cmxQQUZhV2pvanQ1TW9JeTM3UU9vN25WaFlMbnRhb3ExdjQvZWRpdD91c3A9c2hhcmluZykgYW5kIFtUaW1lbGluZSBGb3IgQ2xpZW50IFJlc3BvbnNlc10oaHR0cHM6Ly9kb2NzLmdvb2dsZS5jb20vc3ByZWFkc2hlZXRzL2QvMWljMjNUYnBhbXowdHYzLTRpc055dzJZR3RTT1RWa3lyX1VHMUJIN2xNUVEvZWRpdD91c3A9c2hhcmluZykKYGBge3J9CnByaWNlcyA8LSByZWFkX2V4Y2VsKCIvVXNlcnMvc2h1Ymhhbmthci9EZXNrdG9wL1BSSS9wcmljZXMueGxzeCIsIDEsIGNvbF9uYW1lcyA9IFRSVUUpCnBhdF9vdXRwdXQgPC0gcmVhZF9leGNlbCgiL1VzZXJzL3NodWJoYW5rYXIvRGVza3RvcC9QUkkvUEFUX291dHB1dC54bHN4IiwgMSwgY29sX25hbWVzID0gVFJVRSkKY2xpZW50X3Jlc3BvbnNlXzIwMTQgPC0gcmVhZF9leGNlbCgiL1VzZXJzL3NodWJoYW5rYXIvRGVza3RvcC9QUkkvVGltZWxpbmVGb3JDbGllbnRSZXNwb25zZXMueGxzbSIsIDQsIGNvbF9uYW1lcyA9IFRSVUUpCmNsaWVudF9yZXNwb25zZV8yMDE1IDwtIHJlYWRfZXhjZWwoIi9Vc2Vycy9zaHViaGFua2FyL0Rlc2t0b3AvUFJJL1RpbWVsaW5lRm9yQ2xpZW50UmVzcG9uc2VzLnhsc20iLCA1LCBjb2xfbmFtZXMgPSBUUlVFKQpjbGllbnRfcmVzcG9uc2VfMjAxNiA8LSByZWFkX2V4Y2VsKCIvVXNlcnMvc2h1Ymhhbmthci9EZXNrdG9wL1BSSS9UaW1lbGluZUZvckNsaWVudFJlc3BvbnNlcy54bHNtIiwgNiwgY29sX25hbWVzID0gVFJVRSkKY2xpZW50X3Jlc3BvbnNlXzIwMTcgPC0gcmVhZF9leGNlbCgiL1VzZXJzL3NodWJoYW5rYXIvRGVza3RvcC9QUkkvVGltZWxpbmVGb3JDbGllbnRSZXNwb25zZXMueGxzbSIsIDcsIGNvbF9uYW1lcyA9IFRSVUUpCmBgYAoKCjxicj48YnI+CgojIyMjI0Jhc2ljIGhvdXNla2VlcGluZzogIAoKIyMjIyMjRm9ybWF0dGluZyBmaXJzdCBjb2x1bW4gYXMgZGF0ZSwgc2V0dGluZyB0aW1lLXpvbmUuCmBgYHtyfQpwcmljZXMgPSBhcy5kYXRhLmZyYW1lKHByaWNlcykKcGF0X291dHB1dCA9IGFzLmRhdGEuZnJhbWUocGF0X291dHB1dCkKU3lzLnNldGVudih0eiA9IFN5cy50aW1lem9uZSgpKQppbnZpc2libGUoYXMuUE9TSVhjdChwcmljZXMkRGF0ZSwgdHo9Z2V0T3B0aW9uKCJ0eiIpKSkKaW52aXNpYmxlKGFzLlBPU0lYY3QocGF0X291dHB1dCREYXRlLCB0ej1nZXRPcHRpb24oInR6IikpKQpgYGAKCjxicj48YnI+CgojIyMjI1Bsb3R0aW5nIGNhbGVuZGFyIHllYXIgUHJpY2VzIHZzIFRpbWUuIAoKIyMjIyMjQSBkZXRhaWxlZCBwbG90IGNhbiBiZSB2aWV3ZWQgW2hlcmVdKGh0dHBzOi8vZG9jcy5nb29nbGUuY29tL3NwcmVhZHNoZWV0cy9kLzFJMVVYQjdWNkY3N0FkWWdvekpPYTFwOE1KUUE2VC1uUllmdC1wZTVheUtFL2VkaXQjZ2lkPTIwMzAyNDcyNTUpCmBgYHtyfQpwbG90X2x5KHByaWNlcywgeCA9IHByaWNlcyREYXRlLCB5ID0gcHJpY2VzJFlfMTQsIG5hbWUgPSAnWV8xNCcsIHR5cGUgPSAic2NhdHRlciIsIG1vZGUgPSAnbGluZXMnLCBsaW5lID0gbGlzdCh3aWR0aCA9IDEpLCB3aWR0aCA9IDk1MCkgJT4lCiAgYWRkX3RyYWNlKHkgPSBwcmljZXMkWV8xNSwgbmFtZSA9ICdZXzE1JywgbW9kZSA9ICdsaW5lcycpICU+JQogIGFkZF90cmFjZSh5ID0gcHJpY2VzJFlfMTYsIG5hbWUgPSAnWV8xNicsIG1vZGUgPSAnbGluZXMnKSAlPiUKICBhZGRfdHJhY2UoeSA9IHByaWNlcyRZXzE3LCBuYW1lID0gJ1lfMTcnLCBtb2RlID0gJ2xpbmVzJykgJT4lCiAgYWRkX3RyYWNlKHkgPSBwcmljZXMkWV8xOCwgbmFtZSA9ICdZXzE4JywgbW9kZSA9ICdsaW5lcycpICU+JQogIGFkZF90cmFjZSh5ID0gcHJpY2VzJFlfMTksIG5hbWUgPSAnWV8xOScsIG1vZGUgPSAnbGluZXMnKSAlPiUKICBhZGRfdHJhY2UoeSA9IHByaWNlcyRZXzIwLCBuYW1lID0gJ1lfMjAnLCBtb2RlID0gJ2xpbmVzJykgJT4lCiAgYWRkX3RyYWNlKHkgPSBwcmljZXMkWV8yMSwgbmFtZSA9ICdZXzIxJywgbW9kZSA9ICdsaW5lcycpICU+JSAKICBsYXlvdXQoaG92ZXJtb2RlPSJjb21wYXJlIikKYGBgCgoKPGJyPjxicj4KCiMjIyMjUGxvdHRpbmcgQU0gUHJpY2VzIHZzIFRpbWUuIAoKIyMjIyMjQSBkZXRhaWxlZCBwbG90IGNhbiBiZSB2aWV3ZWQgW2hlcmVdKCMpCmBgYHtyfQpwbG90X2x5KHByaWNlcywgeCA9IHByaWNlcyREYXRlLCB5ID0gcHJpY2VzJFlfMTRBTSwgbmFtZSA9ICdZXzE0QU0nLCB0eXBlID0gInNjYXR0ZXIiLCBtb2RlID0gJ2xpbmVzJywgbGluZSA9IGxpc3Qod2lkdGggPSAxKSwgd2lkdGggPSA5NTApICU+JQogIGFkZF90cmFjZSh5ID0gcHJpY2VzJFlfMTVBTSwgbmFtZSA9ICdZXzE1QU0nLCBtb2RlID0gJ2xpbmVzJykgJT4lCiAgYWRkX3RyYWNlKHkgPSBwcmljZXMkWV8xNkFNLCBuYW1lID0gJ1lfMTZBTScsIG1vZGUgPSAnbGluZXMnKSAlPiUKICBhZGRfdHJhY2UoeSA9IHByaWNlcyRZXzE3QU0sIG5hbWUgPSAnWV8xN0FNJywgbW9kZSA9ICdsaW5lcycpICU+JQogIGFkZF90cmFjZSh5ID0gcHJpY2VzJFlfMThBTSwgbmFtZSA9ICdZXzE4QU0nLCBtb2RlID0gJ2xpbmVzJykgJT4lCiAgYWRkX3RyYWNlKHkgPSBwcmljZXMkWV8xOUFNLCBuYW1lID0gJ1lfMTlBTScsIG1vZGUgPSAnbGluZXMnKSAlPiUKICBhZGRfdHJhY2UoeSA9IHByaWNlcyRZXzIwQU0sIG5hbWUgPSAnWV8yMEFNJywgbW9kZSA9ICdsaW5lcycpICU+JQogIGxheW91dChob3Zlcm1vZGU9ImNvbXBhcmUiKQpgYGAKCgo8YnI+PGJyPgoKIyMjIyNQbG90dGluZyBkaXN0cmlidXRpb24gb2YgcHJpY2VzIGZvciBlYWNoIGNhbGVuZGFyIHllYXIgYW5kIGNvcnJlc3BvbmRpbmcgZmlzY2FsIHllYXI6CgojIyMjIyNZXzE0IGFuZCBZXzE0QU0sIFlfMTUgYW5kIFlfMTVBTSwgWV8xNiBhbmQgWV8xNkFNLCBZXzE3IGFuZCBZXzE3QU0sIFlfMTggYW5kIFlfMThBTSwgWV8xOSBhbmQgWV8xOUFNLCBZXzIwIGFuZCBZXzIwQU0sIFlfMjEgYW5kIFlfMjFBTQpgYGB7cn0KeF9heGlzX3RlbXBsYXRlIDwtIGxpc3Qoc2hvd2dyaWQgPSBGLAogICAgICAgICAgICAgICAgICAgICAgemVyb2xpbmUgPSBGLAogICAgICAgICAgICAgICAgICAgICAgbnRpY2tzID0gMjAsCiAgICAgICAgICAgICAgICAgICAgICBzaG93bGluZSA9IFQsCiAgICAgICAgICAgICAgICAgICAgICB0aWNrMCA9IDAsCiAgICAgICAgICAgICAgICAgICAgICByYW5nZSA9IGMoMjgsNDUpLAogICAgICAgICAgICAgICAgICAgICAgdGl0bGUgPSAiUHJpY2VzIikKeV9heGlzX3RlbXBsYXRlIDwtIGxpc3QobnRpY2tzID0gOCwgcmFuZ2UgPSBjKDAsMTIwKSwgdGl0bGUgPSAiRnJlcXVlbmN5IikKCnN0cmlwcyA8LSBsaXN0KCJZXzE0IiwgIllfMTUiLCAiWV8xNiIsICJZXzE3IiwgIllfMTgiLCAiWV8xOSIsICJZXzIwIiwgIllfMjEiKQpwbG90cyA8LSBsYXBwbHkoc3RyaXBzLCBmdW5jdGlvbih2YXIpewogIEFNIDwtIHBhc3RlKHZhciwiQU0iLCBzZXAgPSAiIikKICBwbG90X2x5KHdpZHRoID0gOTUwKSAlPiUKICBhZGRfaGlzdG9ncmFtKHggPSBwcmljZXNbLHZhcl0sIG5hbWUgPSB2YXIpICU+JQogIGFkZF9oaXN0b2dyYW0oeCA9IHByaWNlc1ssQU1dLCBuYW1lID0gQU0pICU+JQogIGxheW91dCh4YXhpcyA9IHhfYXhpc190ZW1wbGF0ZSwgeWF4aXMgPSB5X2F4aXNfdGVtcGxhdGUsIGhvdmVybW9kZT0iY29tcGFyZSIpCn0pCnN1YnBsb3QocGxvdHMsIG5yb3dzID0gNCwgc2hhcmVYID0gVFJVRSwgc2hhcmVZID0gVFJVRSkKYGBgCgoKPGJyPjxicj4gU2luY2UgdGhlIFtudW1iZXIgb2YgZGF5cyBvZiBoaXN0b3JpY2FsIGRhdGEgdG8gdXNlIGluIGNhbGN1bGF0aW9ucyBpcyBzZXQgdG8gMTAwIGRheXNdKGh0dHBzOi8vZG9jcy5nb29nbGUuY29tL2RvY3VtZW50L2QvMWJ4dmVQNXdncUVtVjl4Wlk4YTUtaEw0THVZd01xQlljZ3ZWNFFqNzVrWkUvZWRpdCNib29rbWFyaz1pZC5kaW44d3RycGx0ZDcpIHRoZXJlZm9yZSB3ZSBza2lwIHRoZSBwcmljZXMgZm9yIGZpcnN0IDEwMCBkYXlzIGluIGVhY2ggc3RyaXAgYW5kIHVzZSB0aGUgc3Vic2VxdWVudCBwcmljZXMgdG8gZ2VuZXJhdGUgcmVjb21tZW5kYXRpb25zLiBBcyBhIGNvbnNlcXVlbmNlIG9mIHNraXBwaW5nIHdlIGFyZSBsZWZ0IHdpdGggbm8gcHJpY2VzIGZvciB0aGUgc3RyaXAgWV8xNCBhbmQgdmVyeSBmZXcgZW50cmllcyBmb3IgdGhlIHN0cmlwIFlfMTRBTS4gVGh1cyB3ZSB3aWxsIGNvbnNpZGVyIHRoZSBwcmljZXMgb2Ygc3RyaXBzIFlfMTRBTSBvbndhcmRzIGZvciBldmFsdWF0aW5nIHRoZSBQQVQuIAoKPGJyPgoKIyMjIyNQcmVsaW1pbmFyeSBBbmFseXNpcwoKU3BsaXQgUEFUIG91dHB1dCBieSByZXNwZWN0aXZlIGNvbnRyYWN0IHllYXJzLgpgYGB7cn0KcGF0X291dHB1dCA8LSBwYXRfb3V0cHV0W29yZGVyKHBhdF9vdXRwdXQkQ29udHJhY3QpLCBdCllfMTRBTSA8LSBwYXRfb3V0cHV0W3BhdF9vdXRwdXQkQ29udHJhY3Q9PSJZXzE0QU0iLF0KWV8xNSA8LSBwYXRfb3V0cHV0W3BhdF9vdXRwdXQkQ29udHJhY3Q9PSJZXzE1IixdCllfMTVBTSA8LSBwYXRfb3V0cHV0W3BhdF9vdXRwdXQkQ29udHJhY3Q9PSJZXzE1QU0iLF0KWV8xNiA8LSBwYXRfb3V0cHV0W3BhdF9vdXRwdXQkQ29udHJhY3Q9PSJZXzE2IixdCllfMTZBTSA8LSBwYXRfb3V0cHV0W3BhdF9vdXRwdXQkQ29udHJhY3Q9PSJZXzE2QU0iLF0KWV8xNyA8LSBwYXRfb3V0cHV0W3BhdF9vdXRwdXQkQ29udHJhY3Q9PSJZXzE3IixdCllfMTdBTSA8LSBwYXRfb3V0cHV0W3BhdF9vdXRwdXQkQ29udHJhY3Q9PSJZXzE3QU0iLF0KYGBgCgo8YnI+PGJyPgoKU2NhdHRlci1saW5lIHBsb3RzIHNob3dpbmcgcHJpY2VzIGFuZCBkaXN0cmlidXRpb24gb2YgaGVkZ2luZyBvcHBvcnR1bml0aWVzIGFjcm9zcyB0aW1lIGZvciBlYWNoIHN0cmlwLiBBIHJlZCBkb3QgcmVwcmVzZW50cyAiNSAtIEdyZWF0IGhlZGdpbmcgb3Bwb3J0dW5pdHkiIGFuZCBhIHllbGxvdyBkb3QgcmVwcmVzZW50cyAiNCAtIFZlcnkgZ29vZCBoZWRnaW5nIG9wcG9ydHVuaXR5Ii4KYGBge3J9CiNZXzE0QU0KcGxvdFlfMTRBTSA8LSBwbG90X2x5KFlfMTRBTSwgeCA9IFlfMTRBTSREYXRlLCB5ID0gWV8xNEFNJFByaWNlLCBuYW1lID0gJ1lfMTRBTScsIHR5cGUgPSAic2NhdHRlciIsIG1vZGUgPSAnbGluZXMnLCBsaW5lID0gbGlzdCh3aWR0aCA9IDEpLCB3aWR0aCA9IDk1MCwgaGVpZ2h0ID0gNTAwKSAlPiUgbGF5b3V0KGhvdmVybW9kZT0iY29tcGFyZSIsIHlheGlzID0gbGlzdCh0aXRsZSA9ICJQcmljZSIpLCBzaG93bGVnZW5kID0gVCkKZm9yKGkgaW4gWV8xNEFNW1lfMTRBTSRSZWNvbW1lbmRhdGlvbiA9PSAiNSAtIEdyZWF0IGhlZGdpbmcgb3Bwb3J0dW5pdHkiLDNdKXsKICBwbG90WV8xNEFNIDwtIGFkZF90cmFjZShwbG90WV8xNEFNLCB4ID0gKGFzLm51bWVyaWMoYXMuRGF0ZShZXzE0QU1bWV8xNEFNJFByaWNlID09IGksMV0pKSAqIDI0ICogNjAgKiA2MCAqIDEwMDApLCB5ID0gaSwgbW9kZSA9ICJtYXJrZXJzK2xpbmVzIiwgc2hvd2xlZ2VuZCA9IEYsIG1hcmtlciA9IGxpc3QoY29sb3I9InJlZCIsIHNpemU9NSwgb3BhY2l0eT0wLjUpKQp9CmZvcihpIGluIFlfMTRBTVtZXzE0QU0kUmVjb21tZW5kYXRpb24gPT0gIjQgLSBWZXJ5IGdvb2QgaGVkZ2luZyBvcHBvcnR1bml0eSIsM10pewogIHBsb3RZXzE0QU0gPC0gYWRkX3RyYWNlKHBsb3RZXzE0QU0sIHggPSAoYXMubnVtZXJpYyhhcy5EYXRlKFlfMTRBTVtZXzE0QU0kUHJpY2UgPT0gaSwxXSkpICogMjQgKiA2MCAqIDYwICogMTAwMCksIHkgPSBpLCBtb2RlID0gIm1hcmtlcnMrbGluZXMiLCBzaG93bGVnZW5kID0gRiwgbWFya2VyID0gbGlzdChjb2xvcj0ib3JhbmdlIiwgc2l6ZT01LCBvcGFjaXR5PTAuNSkpCn0KCiNZXzE1CnBsb3RZXzE1IDwtIHBsb3RfbHkoWV8xNSwgeCA9IFlfMTUkRGF0ZSwgeSA9IFlfMTUkUHJpY2UsIG5hbWUgPSAnWV8xNScsIHR5cGUgPSAic2NhdHRlciIsIG1vZGUgPSAnbGluZXMnLCBsaW5lID0gbGlzdCh3aWR0aCA9IDEpLCB3aWR0aCA9IDk1MCwgaGVpZ2h0ID0gNTAwKSAlPiUKbGF5b3V0KGhvdmVybW9kZT0iY29tcGFyZSIsIHlheGlzID0gbGlzdCh0aXRsZSA9ICJQcmljZSIpLCBzaG93bGVnZW5kID0gVCkKZm9yKGkgaW4gWV8xNVtZXzE1JFJlY29tbWVuZGF0aW9uID09ICI1IC0gR3JlYXQgaGVkZ2luZyBvcHBvcnR1bml0eSIsM10pewogIHBsb3RZXzE1IDwtIGFkZF90cmFjZShwbG90WV8xNSwgeCA9IChhcy5udW1lcmljKGFzLkRhdGUoWV8xNVtZXzE1JFByaWNlID09IGksMV0pKSAqIDI0ICogNjAgKiA2MCAqIDEwMDApLCB5ID0gaSwgbW9kZSA9ICJtYXJrZXJzK2xpbmVzIiwgc2hvd2xlZ2VuZCA9IEYsIG1hcmtlciA9IGxpc3QoY29sb3I9InJlZCIsIHNpemU9NSwgb3BhY2l0eT0wLjUpKQp9CmZvcihpIGluIFlfMTVbWV8xNSRSZWNvbW1lbmRhdGlvbiA9PSAiNCAtIFZlcnkgZ29vZCBoZWRnaW5nIG9wcG9ydHVuaXR5IiwzXSl7CiAgcGxvdFlfMTUgPC0gYWRkX3RyYWNlKHBsb3RZXzE1LCB4ID0gKGFzLm51bWVyaWMoYXMuRGF0ZShZXzE1W1lfMTUkUHJpY2UgPT0gaSwxXSkpICogMjQgKiA2MCAqIDYwICogMTAwMCksIHkgPSBpLCBtb2RlID0gIm1hcmtlcnMrbGluZXMiLCBzaG93bGVnZW5kID0gRiwgbWFya2VyID0gbGlzdChjb2xvcj0ib3JhbmdlIiwgc2l6ZT01LCBvcGFjaXR5PTAuNSkpCn0KCiNZXzE1QU0KcGxvdFlfMTVBTSA8LSBwbG90X2x5KFlfMTVBTSwgeCA9IFlfMTVBTSREYXRlLCB5ID0gWV8xNUFNJFByaWNlLCBuYW1lID0gJ1lfMTVBTScsIHR5cGUgPSAic2NhdHRlciIsIG1vZGUgPSAnbGluZXMnLCBsaW5lID0gbGlzdCh3aWR0aCA9IDEpLCB3aWR0aCA9IDk1MCwgaGVpZ2h0ID0gNTAwKSAlPiUKbGF5b3V0KGhvdmVybW9kZT0iY29tcGFyZSIsIHlheGlzID0gbGlzdCh0aXRsZSA9ICJQcmljZSIpLCBzaG93bGVnZW5kID0gVCkKZm9yKGkgaW4gWV8xNUFNW1lfMTVBTSRSZWNvbW1lbmRhdGlvbiA9PSAiNSAtIEdyZWF0IGhlZGdpbmcgb3Bwb3J0dW5pdHkiLDNdKXsKICBwbG90WV8xNUFNIDwtIGFkZF90cmFjZShwbG90WV8xNUFNLCB4ID0gKGFzLm51bWVyaWMoYXMuRGF0ZShZXzE1QU1bWV8xNUFNJFByaWNlID09IGksMV0pKSAqIDI0ICogNjAgKiA2MCAqIDEwMDApLCB5ID0gaSwgbW9kZSA9ICJtYXJrZXJzK2xpbmVzIiwgc2hvd2xlZ2VuZCA9IEYsIG1hcmtlciA9IGxpc3QoY29sb3I9InJlZCIsIHNpemU9NSwgb3BhY2l0eT0wLjUpKQp9CmZvcihpIGluIFlfMTVBTVtZXzE1QU0kUmVjb21tZW5kYXRpb24gPT0gIjQgLSBWZXJ5IGdvb2QgaGVkZ2luZyBvcHBvcnR1bml0eSIsM10pewogIHBsb3RZXzE1QU0gPC0gYWRkX3RyYWNlKHBsb3RZXzE1QU0sIHggPSAoYXMubnVtZXJpYyhhcy5EYXRlKFlfMTVBTVtZXzE1QU0kUHJpY2UgPT0gaSwxXSkpICogMjQgKiA2MCAqIDYwICogMTAwMCksIHkgPSBpLCBtb2RlID0gIm1hcmtlcnMrbGluZXMiLCBzaG93bGVnZW5kID0gRiwgbWFya2VyID0gbGlzdChjb2xvcj0ib3JhbmdlIiwgc2l6ZT01LCBvcGFjaXR5PTAuNSkpCn0KCgojWV8xNgpwbG90WV8xNiA8LSBwbG90X2x5KFlfMTYsIHggPSBZXzE2JERhdGUsIHkgPSBZXzE2JFByaWNlLCBuYW1lID0gJ1lfMTYnLCB0eXBlID0gInNjYXR0ZXIiLCBtb2RlID0gJ2xpbmVzJywgbGluZSA9IGxpc3Qod2lkdGggPSAxKSwgd2lkdGggPSA5NTAsIGhlaWdodCA9IDUwMCkgJT4lCmxheW91dChob3Zlcm1vZGU9ImNvbXBhcmUiLCB5YXhpcyA9IGxpc3QodGl0bGUgPSAiUHJpY2UiKSwgc2hvd2xlZ2VuZCA9IFQpCmZvcihpIGluIFlfMTZbWV8xNiRSZWNvbW1lbmRhdGlvbiA9PSAiNSAtIEdyZWF0IGhlZGdpbmcgb3Bwb3J0dW5pdHkiLDNdKXsKICBwbG90WV8xNiA8LSBhZGRfdHJhY2UocGxvdFlfMTYsIHggPSAoYXMubnVtZXJpYyhhcy5EYXRlKFlfMTZbWV8xNiRQcmljZSA9PSBpLDFdKSkgKiAyNCAqIDYwICogNjAgKiAxMDAwKSwgeSA9IGksIG1vZGUgPSAibWFya2VycytsaW5lcyIsIHNob3dsZWdlbmQgPSBGLCBtYXJrZXIgPSBsaXN0KGNvbG9yPSJyZWQiLCBzaXplPTUsIG9wYWNpdHk9MC41KSkKfQpmb3IoaSBpbiBZXzE2W1lfMTYkUmVjb21tZW5kYXRpb24gPT0gIjQgLSBWZXJ5IGdvb2QgaGVkZ2luZyBvcHBvcnR1bml0eSIsM10pewogIHBsb3RZXzE2IDwtIGFkZF90cmFjZShwbG90WV8xNiwgeCA9IChhcy5udW1lcmljKGFzLkRhdGUoWV8xNltZXzE2JFByaWNlID09IGksMV0pKSAqIDI0ICogNjAgKiA2MCAqIDEwMDApLCB5ID0gaSwgbW9kZSA9ICJtYXJrZXJzK2xpbmVzIiwgc2hvd2xlZ2VuZCA9IEYsIG1hcmtlciA9IGxpc3QoY29sb3I9Im9yYW5nZSIsIHNpemU9NSwgb3BhY2l0eT0wLjUpKQp9CgojWV8xNkFNCnBsb3RZXzE2QU0gPC0gcGxvdF9seShZXzE2QU0sIHggPSBZXzE2QU0kRGF0ZSwgeSA9IFlfMTZBTSRQcmljZSwgbmFtZSA9ICdZXzE2QU0nLCB0eXBlID0gInNjYXR0ZXIiLCBtb2RlID0gJ2xpbmVzJywgbGluZSA9IGxpc3Qod2lkdGggPSAxKSwgd2lkdGggPSA5NTAsIGhlaWdodCA9IDUwMCkgJT4lCmxheW91dChob3Zlcm1vZGU9ImNvbXBhcmUiLCB5YXhpcyA9IGxpc3QodGl0bGUgPSAiUHJpY2UiKSwgc2hvd2xlZ2VuZCA9IFQpCmZvcihpIGluIFlfMTZBTVtZXzE2QU0kUmVjb21tZW5kYXRpb24gPT0gIjUgLSBHcmVhdCBoZWRnaW5nIG9wcG9ydHVuaXR5IiwzXSl7CiAgcGxvdFlfMTZBTSA8LSBhZGRfdHJhY2UocGxvdFlfMTZBTSwgeCA9IChhcy5udW1lcmljKGFzLkRhdGUoWV8xNkFNW1lfMTZBTSRQcmljZSA9PSBpLDFdKSkgKiAyNCAqIDYwICogNjAgKiAxMDAwKSwgeSA9IGksIG1vZGUgPSAibWFya2VycytsaW5lcyIsIHNob3dsZWdlbmQgPSBGLCBtYXJrZXIgPSBsaXN0KGNvbG9yPSJyZWQiLCBzaXplPTUsIG9wYWNpdHk9MC41KSkKfQpmb3IoaSBpbiBZXzE2QU1bWV8xNkFNJFJlY29tbWVuZGF0aW9uID09ICI0IC0gVmVyeSBnb29kIGhlZGdpbmcgb3Bwb3J0dW5pdHkiLDNdKXsKICBwbG90WV8xNkFNIDwtIGFkZF90cmFjZShwbG90WV8xNkFNLCB4ID0gKGFzLm51bWVyaWMoYXMuRGF0ZShZXzE2QU1bWV8xNkFNJFByaWNlID09IGksMV0pKSAqIDI0ICogNjAgKiA2MCAqIDEwMDApLCB5ID0gaSwgbW9kZSA9ICJtYXJrZXJzK2xpbmVzIiwgc2hvd2xlZ2VuZCA9IEYsIG1hcmtlciA9IGxpc3QoY29sb3I9Im9yYW5nZSIsIHNpemU9NSwgb3BhY2l0eT0wLjUpKQp9CgojWV8xNwpwbG90WV8xNyA8LSBwbG90X2x5KFlfMTcsIHggPSBZXzE3JERhdGUsIHkgPSBZXzE3JFByaWNlLCBuYW1lID0gJ1lfMTcnLCB0eXBlID0gInNjYXR0ZXIiLCBtb2RlID0gJ2xpbmVzJywgbGluZSA9IGxpc3Qod2lkdGggPSAxKSwgd2lkdGggPSA5NTAsIGhlaWdodCA9IDUwMCkgJT4lCmxheW91dChob3Zlcm1vZGU9ImNvbXBhcmUiLCB5YXhpcyA9IGxpc3QodGl0bGUgPSAiUHJpY2UiKSwgc2hvd2xlZ2VuZCA9IFQpCmZvcihpIGluIFlfMTdbWV8xNyRSZWNvbW1lbmRhdGlvbiA9PSAiNSAtIEdyZWF0IGhlZGdpbmcgb3Bwb3J0dW5pdHkiLDNdKXsKICBwbG90WV8xNyA8LSBhZGRfdHJhY2UocGxvdFlfMTcsIHggPSAoYXMubnVtZXJpYyhhcy5EYXRlKFlfMTdbWV8xNyRQcmljZSA9PSBpLDFdKSkgKiAyNCAqIDYwICogNjAgKiAxMDAwKSwgeSA9IGksIG1vZGUgPSAibWFya2VycytsaW5lcyIsIHNob3dsZWdlbmQgPSBGLCBtYXJrZXIgPSBsaXN0KGNvbG9yPSJyZWQiLCBzaXplPTUsIG9wYWNpdHk9MC41KSkKfQpmb3IoaSBpbiBZXzE3W1lfMTckUmVjb21tZW5kYXRpb24gPT0gIjQgLSBWZXJ5IGdvb2QgaGVkZ2luZyBvcHBvcnR1bml0eSIsM10pewogIHBsb3RZXzE3IDwtIGFkZF90cmFjZShwbG90WV8xNywgeCA9IChhcy5udW1lcmljKGFzLkRhdGUoWV8xN1tZXzE3JFByaWNlID09IGksMV0pKSAqIDI0ICogNjAgKiA2MCAqIDEwMDApLCB5ID0gaSwgbW9kZSA9ICJtYXJrZXJzK2xpbmVzIiwgc2hvd2xlZ2VuZCA9IEYsIG1hcmtlciA9IGxpc3QoY29sb3I9Im9yYW5nZSIsIHNpemU9NSwgb3BhY2l0eT0wLjUpKQp9CgojWV8xN0FNCnBsb3RZXzE3QU0gPC0gcGxvdF9seShZXzE3QU0sIHggPSBZXzE3QU0kRGF0ZSwgeSA9IFlfMTdBTSRQcmljZSwgbmFtZSA9ICdZXzE3QU0nLCB0eXBlID0gInNjYXR0ZXIiLCBtb2RlID0gJ2xpbmVzJywgbGluZSA9IGxpc3Qod2lkdGggPSAxKSwgd2lkdGggPSA5NTAsIGhlaWdodCA9IDQ1MCkgJT4lCmxheW91dChob3Zlcm1vZGU9ImNvbXBhcmUiLCB5YXhpcyA9IGxpc3QodGl0bGUgPSAiUHJpY2UiKSwgc2hvd2xlZ2VuZCA9IFQgKQpmb3IoaSBpbiBZXzE3QU1bWV8xN0FNJFJlY29tbWVuZGF0aW9uID09ICI1IC0gR3JlYXQgaGVkZ2luZyBvcHBvcnR1bml0eSIsM10pewogIHBsb3RZXzE3QU0gPC0gYWRkX3RyYWNlKHBsb3RZXzE3QU0sIHggPSAoYXMubnVtZXJpYyhhcy5EYXRlKFlfMTdBTVtZXzE3QU0kUHJpY2UgPT0gaSwxXSkpICogMjQgKiA2MCAqIDYwICogMTAwMCksIHkgPSBpLCBtb2RlID0gIm1hcmtlcnMrbGluZXMiLCBzaG93bGVnZW5kID0gRiwgbWFya2VyID0gbGlzdChjb2xvcj0icmVkIiwgc2l6ZT01LCBvcGFjaXR5PTAuNSkpCn0KZm9yKGkgaW4gWV8xN0FNW1lfMTdBTSRSZWNvbW1lbmRhdGlvbiA9PSAiNCAtIFZlcnkgZ29vZCBoZWRnaW5nIG9wcG9ydHVuaXR5IiwzXSl7CiAgcGxvdFlfMTdBTSA8LSBhZGRfdHJhY2UocGxvdFlfMTdBTSwgeCA9IChhcy5udW1lcmljKGFzLkRhdGUoWV8xN0FNW1lfMTdBTSRQcmljZSA9PSBpLDFdKSkgKiAyNCAqIDYwICogNjAgKiAxMDAwKSwgeSA9IGksIG1vZGUgPSAibWFya2VycytsaW5lcyIsIHNob3dsZWdlbmQgPSBGLCBtYXJrZXIgPSBsaXN0KGNvbG9yPSJvcmFuZ2UiLCBzaXplPTUsIG9wYWNpdHk9MC41KSkKfQpgYGAKCjxicj48YnI+CgojIyMjI1lfMTRBTQpgYGB7cn0KcGxvdFlfMTRBTQpgYGAKCjxicj48YnI+CgojIyMjI1lfMTUKYGBge3J9CnBsb3RZXzE1CmBgYAoKPGJyPjxicj4KCiMjIyMjWV8xNUFNCmBgYHtyfQpwbG90WV8xNUFNCmBgYAoKPGJyPjxicj4KCiMjIyMjWV8xNgpgYGB7cn0KcGxvdFlfMTYKYGBgCgoKPGJyPjxicj4KCiMjIyMjWV8xNkFNCmBgYHtyfQpwbG90WV8xNkFNCmBgYAoKPGJyPjxicj4KCiMjIyMjWV8xNwpgYGB7cn0KcGxvdFlfMTcKYGBgCgo8YnI+PGJyPgoKIyMjIyNZXzE3QU0KYGBge3J9CnBsb3RZXzE3QU0KYGBgCgoKCjxicj48YnI+CgpWaW9saW4gcGxvdHMgc2hvd2luZyBwcmljZSBkZW5zaXR5IGFuZCBkaXN0cmlidXRpb24gb2YgaGVkZ2luZyBvcHBvcnR1bml0aWVzIGFjcm9zcyBwcmljZXMgZm9yIGVhY2ggc3RyaXAuIFRoaWNrZXIgdGhlIHBsb3QgaGlnaGVyIHRoZSBmcmVxdWVuY3kgb2YgdGhlIHByaWNlcyBpbiB0aGF0IG5laWdoYm9yaG9vZC4gQSByZWQgZG90IHJlcHJlc2VudHMgIjUgLSBHcmVhdCBoZWRnaW5nIG9wcG9ydHVuaXR5IiBhbmQgYSB5ZWxsb3cgZG90IHJlcHJlc2VudHMgIjQgLSBWZXJ5IGdvb2QgaGVkZ2luZyBvcHBvcnR1bml0eSIuIEhvcml6b250YWwgY3Jvc3NiYXIoYmxhY2spIHNob3dzIHRoZSBtZWRpYW4gcHJpY2UgZm9yIHRoYXQgc3RyaXAuCmBgYHtyfQpnZ3Bsb3Qod2lkdGggPSA5NTAsIHBhdF9vdXRwdXQsIGFlcyhDb250cmFjdCwgUHJpY2UpKSArIGdlb21fdmlvbGluKGFlcyhmaWxsID0gQ29udHJhY3QpKSArIHNjYWxlX2ZpbGxfbWFudWFsKHZhbHVlcz1jKCIjQjRFMEQyIiwgIiNGQ0M2QjMiLCAiI0M2Q0ZFNCIsICIjRjJDNUUwIiwgIiNEM0VBQUQiLCAiI0ZFRUJBMSIsICIjRjFFMUNBIikpICsgZ2VvbV9wb2ludChkYXRhPXBhdF9vdXRwdXRbcGF0X291dHB1dCRSZWNvbW1lbmRhdGlvbj09IjUgLSBHcmVhdCBoZWRnaW5nIG9wcG9ydHVuaXR5IixdLCBhZXMoQ29udHJhY3QsIFByaWNlKSwgY29sb3IgPSAiI0I0MDYxOSIsIHBvc2l0aW9uID0gcG9zaXRpb25faml0dGVyKDAuMDkpLCBzaXplID0gMC41KSArIGdlb21fcG9pbnQoZGF0YT1wYXRfb3V0cHV0W3BhdF9vdXRwdXQkUmVjb21tZW5kYXRpb249PSI0IC0gVmVyeSBnb29kIGhlZGdpbmcgb3Bwb3J0dW5pdHkiLF0sIGFlcyhDb250cmFjdCwgUHJpY2UpLCBjb2xvciA9ICIjRTU2NjIxIiwgcG9zaXRpb24gPSBwb3NpdGlvbl9qaXR0ZXIoMC4wOSksIHNpemUgPSAwLjUpICsgc3RhdF9zdW1tYXJ5KGZ1bi55ID0gIm1lZGlhbiIsIGZ1bi55bWluID0ibWVkaWFuIiwgZnVuLnltYXggPSJtZWRpYW4iLCBnZW9tID0iY3Jvc3NiYXIiLCB3aWR0aD0wLjIsIGZhdHRlbiA9IDEpCmBgYAoKPGJyPjxicj4KCkJveHBsb3Qgc2hvd2luZyBtZWRpYW4sIGZpcnN0LCBzZWNvbmQsIHRoaXJkIGFuZCBmb3VydGggcXVhcnRpbGUgb2YgcHJpY2VzIGZvciBlYWNoIHN0cmlwLgpgYGB7cn0KYm94MSA8LSBwbG90X2x5KHBhdF9vdXRwdXQsIHggPSB+Q29udHJhY3QsIHkgPSB+UHJpY2UsIGNvbG9yID0gfkNvbnRyYWN0LCB0eXBlID0gImJveCIsIGJveHBvaW50cyA9IEZBTFNFLCB3aWR0aCA9IDk1MCkgJT4lCiAgbGF5b3V0KGhvdmVybW9kZT0iY29tcGFyZSIpCgpoZWRnZV9wcmljZV9ib3hwbG90IDwtIGRhdGEuZnJhbWUoQ29udHJhY3QgPSBwYXRfb3V0cHV0W3BhdF9vdXRwdXQkUmVjb21tZW5kYXRpb24gPT0gIjUgLSBHcmVhdCBoZWRnaW5nIG9wcG9ydHVuaXR5IiB8IHBhdF9vdXRwdXQkUmVjb21tZW5kYXRpb24gPT0gIjQgLSBWZXJ5IGdvb2QgaGVkZ2luZyBvcHBvcnR1bml0eSIsICJDb250cmFjdCJdLCBQcmljZSA9IHBhdF9vdXRwdXRbcGF0X291dHB1dCRSZWNvbW1lbmRhdGlvbiA9PSAiNSAtIEdyZWF0IGhlZGdpbmcgb3Bwb3J0dW5pdHkiIHwgcGF0X291dHB1dCRSZWNvbW1lbmRhdGlvbiA9PSAiNCAtIFZlcnkgZ29vZCBoZWRnaW5nIG9wcG9ydHVuaXR5IiwgIlByaWNlIl0pCmJveDIgPC0gcGxvdF9seShoZWRnZV9wcmljZV9ib3hwbG90LCB4ID0gaGVkZ2VfcHJpY2VfYm94cGxvdCRDb250cmFjdCwgeSA9IGhlZGdlX3ByaWNlX2JveHBsb3QkUHJpY2UsIGNvbG9yID0gfkNvbnRyYWN0LCB0eXBlID0gImJveCIsIGJveHBvaW50cyA9IEZBTFNFLCB3aWR0aCA9IDk1MCkgJT4lCiAgbGF5b3V0KGhvdmVybW9kZT0iY29tcGFyZSIsIHRpdGxlID0gIkJveHBsb3Qgb2YgYWxsIHByaWNlcyhsZWZ0KSBWcy4gUHJpY2VzIG9mIEdyZWF0ICYgVi4gR29vZCBIZWRnZSBvcHBvcnR1bml0aWVzKHJpZ2h0KSIsIHNob3dsZWdlbmQgPSBGKQoKc3VicGxvdChib3gxLCBib3gyLCBzaGFyZVkgPSBUKQpgYGAKCgoKCjxicj48YnI+CkdhdGhlciBzb21lIGJhc2ljIHN0YXRpc3RpY3MgYWJvdXQgdGhlIFBBVCBvdXRwdXQKYGBge3J9CnllYXJfc3RyaXBzIDwtIGxpc3QoWV8xNEFNLCBZXzE1LCBZXzE1QU0sIFlfMTYsIFlfMTZBTSwgWV8xNywgWV8xN0FNKQpmcmFjdGlvbiA8LSBmdW5jdGlvbihzdHJpcCl7CiAgeWVhck9yZGVyZWRCeVByaWNlIDwtIHN0cmlwW29yZGVyKC1zdHJpcCRQcmljZSksXQogIGZpcnN0X3F1YXJ0aWxlIDwtIHllYXJPcmRlcmVkQnlQcmljZVtjKDE6dHJ1bmMobnJvdyh5ZWFyT3JkZXJlZEJ5UHJpY2UpLzQpKSxdCiAgc2Vjb25kX3F1YXJ0aWxlIDwtIHllYXJPcmRlcmVkQnlQcmljZVtjKCh0cnVuYyhucm93KHllYXJPcmRlcmVkQnlQcmljZSkvNCkrMSk6dHJ1bmMobnJvdyh5ZWFyT3JkZXJlZEJ5UHJpY2UpLzIpKSxdCiAgdGhpcmRfcXVhcnRpbGUgPC0geWVhck9yZGVyZWRCeVByaWNlW2MoKHRydW5jKG5yb3coeWVhck9yZGVyZWRCeVByaWNlKS8yKSsxKTp0cnVuYyhucm93KHllYXJPcmRlcmVkQnlQcmljZSkqMy80KSksXQogIGZvdXJ0aF9xdWFydGlsZSA8LSB5ZWFyT3JkZXJlZEJ5UHJpY2VbYygodHJ1bmMobnJvdyh5ZWFyT3JkZXJlZEJ5UHJpY2UpKjMvNCkrMSk6dHJ1bmMobnJvdyh5ZWFyT3JkZXJlZEJ5UHJpY2UpKSksXQogIAogIG51bU9mR3JlYXRJbkZpcnN0UXVhcnRpbGUgPC0gc3VtKGZpcnN0X3F1YXJ0aWxlJFJlY29tbWVuZGF0aW9uID09ICI1IC0gR3JlYXQgaGVkZ2luZyBvcHBvcnR1bml0eSIpCiAgbnVtT2ZWZXJ5R29vZEluRmlyc3RRdWFydGlsZSA8LSBzdW0oZmlyc3RfcXVhcnRpbGUkUmVjb21tZW5kYXRpb24gPT0gIjQgLSBWZXJ5IGdvb2QgaGVkZ2luZyBvcHBvcnR1bml0eSIpCiAgbnVtT2ZHcmVhdEluU2Vjb25kUXVhcnRpbGUgPC0gc3VtKHNlY29uZF9xdWFydGlsZSRSZWNvbW1lbmRhdGlvbiA9PSAiNSAtIEdyZWF0IGhlZGdpbmcgb3Bwb3J0dW5pdHkiKQogIG51bU9mVmVyeUdvb2RJblNlY29uZFF1YXJ0aWxlIDwtIHN1bShzZWNvbmRfcXVhcnRpbGUkUmVjb21tZW5kYXRpb24gPT0gIjQgLSBWZXJ5IGdvb2QgaGVkZ2luZyBvcHBvcnR1bml0eSIpCiAgbnVtT2ZHcmVhdEluVGhpcmRRdWFydGlsZSA8LSBzdW0odGhpcmRfcXVhcnRpbGUkUmVjb21tZW5kYXRpb24gPT0gIjUgLSBHcmVhdCBoZWRnaW5nIG9wcG9ydHVuaXR5IikKICBudW1PZlZlcnlHb29kSW5UaGlyZFF1YXJ0aWxlIDwtIHN1bSh0aGlyZF9xdWFydGlsZSRSZWNvbW1lbmRhdGlvbiA9PSAiNCAtIFZlcnkgZ29vZCBoZWRnaW5nIG9wcG9ydHVuaXR5IikKICBudW1PZkdyZWF0SW5Gb3VydGhRdWFydGlsZSA8LSBzdW0oZm91cnRoX3F1YXJ0aWxlJFJlY29tbWVuZGF0aW9uID09ICI1IC0gR3JlYXQgaGVkZ2luZyBvcHBvcnR1bml0eSIpCiAgbnVtT2ZWZXJ5R29vZEluRm91cnRoUXVhcnRpbGUgPC0gc3VtKGZvdXJ0aF9xdWFydGlsZSRSZWNvbW1lbmRhdGlvbiA9PSAiNCAtIFZlcnkgZ29vZCBoZWRnaW5nIG9wcG9ydHVuaXR5IikKICBudW1PZk9wcEluRmlyc3RRdWFydGlsZSA8LSBudW1PZkdyZWF0SW5GaXJzdFF1YXJ0aWxlICsgbnVtT2ZWZXJ5R29vZEluRmlyc3RRdWFydGlsZQogIG51bU9mT3BwSW5TZWNvbmRRdWFydGlsZSA8LSBudW1PZkdyZWF0SW5TZWNvbmRRdWFydGlsZSArIG51bU9mVmVyeUdvb2RJblNlY29uZFF1YXJ0aWxlCiAgbnVtT2ZPcHBJblRoaXJkUXVhcnRpbGUgPC0gbnVtT2ZHcmVhdEluVGhpcmRRdWFydGlsZSArIG51bU9mVmVyeUdvb2RJblRoaXJkUXVhcnRpbGUKICBudW1PZk9wcEluRm91cnRoUXVhcnRpbGUgPC0gbnVtT2ZHcmVhdEluRm91cnRoUXVhcnRpbGUgKyBudW1PZlZlcnlHb29kSW5Gb3VydGhRdWFydGlsZQogIGNhdCgiVG90YWwgbm8uIG9mIEdyZWF0IG9yIFYuIEdvb2QgaGVkZ2luZyBvcHBvcnR1bml0aWVzIGZvciB0aGUgc3RyaXAiLHN0cmlwJENvbnRyYWN0WzFdLCI6IixudW1PZk9wcEluRmlyc3RRdWFydGlsZSArIG51bU9mT3BwSW5TZWNvbmRRdWFydGlsZSArIG51bU9mT3BwSW5UaGlyZFF1YXJ0aWxlICsgbnVtT2ZPcHBJbkZvdXJ0aFF1YXJ0aWxlLCAiXG4iICkKICBjYXQoIk5vLiBvZiBHcmVhdCBvciBWLiBHb29kIGhlZGdpbmcgb3Bwb3J0dW5pdGllcyBpbiB0aGUgdG9wIHF1YXJ0ZXIoMC0yNSUsIGZpcnN0IHF1YXJ0aWxlKSBwcmljZXMgZm9yIHRoZSBzdHJpcCIsc3RyaXAkQ29udHJhY3RbMV0sIjoiLG51bU9mT3BwSW5GaXJzdFF1YXJ0aWxlLCAiXG4iKQogIGNhdCgiTm8uIG9mIEdyZWF0IG9yIFYuIEdvb2QgaGVkZ2luZyBvcHBvcnR1bml0aWVzIGluIHRoZSBuZXh0IHF1YXJ0ZXIoMjUlLTUwJSwgc2Vjb25kIHF1YXJ0aWxlKSBwcmljZXMgZm9yIHRoZSBzdHJpcCIsc3RyaXAkQ29udHJhY3RbMV0sIjoiLG51bU9mT3BwSW5TZWNvbmRRdWFydGlsZSwgIlxuIikKICBjYXQoIk5vLiBvZiBHcmVhdCBvciBWLiBHb29kIGhlZGdpbmcgb3Bwb3J0dW5pdGllcyBpbiB0aGUgbmV4dCBxdWFydGVyKDUwJS03NSUsIHRoaXJkIHF1YXJ0aWxlKSBwcmljZXMgZm9yIHRoZSBzdHJpcCIsc3RyaXAkQ29udHJhY3RbMV0sIjoiLG51bU9mT3BwSW5UaGlyZFF1YXJ0aWxlLCAiXG4iKQogIGNhdCgiTm8uIG9mIEdyZWF0IG9yIFYuIEdvb2QgaGVkZ2luZyBvcHBvcnR1bml0aWVzIGluIHRoZSBib3R0b20gcXVhcnRlcig3NSUtMTAwJSwgZm91cnRoIHF1YXJ0aWxlKSBwcmljZXMgZm9yIHRoZSBzdHJpcCIsc3RyaXAkQ29udHJhY3RbMV0sIjoiLG51bU9mT3BwSW5Gb3VydGhRdWFydGlsZSwgIlxuXG4iKQogIAp9Cgpmb3IoaSBpbiB5ZWFyX3N0cmlwcyl7CiAgZnJhY3Rpb24oaSkKfQpgYGAKCgo8YnI+PGJyPgoKIyMjI0V2YWx1YXRpbmcgUEFUCgpUbyBldmFsdWF0ZSBQQVQgbW9yZSByZWFsaXN0aWNhbGx5IHdlIGNhbGN1bGF0ZSB3ZWlnaHRlZCBhdmVyYWdlIHByaWNlcyBieSBpbmNvcnBvcmF0aW5nIFtkZWxheXMgaW4gY2xpZW50IHJlc3BvbnNlIHRpbWVdKGh0dHBzOi8vZG9jcy5nb29nbGUuY29tL3NwcmVhZHNoZWV0cy9kLzFpYzIzVGJwYW16MHR2My00aXNOeXcyWUd0U09UVmt5cl9VRzFCSDdsTVFRL2VkaXQ/dXNwPXNoYXJpbmcpLiAKV2UgdXNlIHR3byBhcHByb2FjaGVzIHRvIGNhbGN1bGF0ZSB0aGUgd2VpZ2h0ZWQgYXZlcmFnZXM6CgpfMSkgQXZlcmFnZWQgYWxsIGF0IG9uY2U6XwpOdW1iZXIgb2YgY2xpZW50IHJlc3BvbnNlcyBmb3IgZWFjaCBkYXRlIGFyZSBzdW1tZWQgdG9nZXRoZXIgYW5kIGRpdmlkZWQgYnkgdG90YWwgbnVtYmVyIG9mIGNsaWVudCByZXNwb25zZXMuCgokJCBBdmVyYWdlXCxjbGllbnRcLHJlc3BvbnNlc1wsb25cLFwsa157dGh9XCxcLGRheVwsPVwsXGZyYWN7XHN1bShDbGllbnRcLHJlc3BvbnNlc1wsb25cLGtee3RofVwsZGF5XCxmb3JcLGVhY2hcLGRhdGUpfXtcc3VtKE51bWJlclwsb2ZcLGNsaWVudFwscmVzcG9uc2VzXCxmb3JcLGVhY2hcLGRhdGUpfSAkJApgYGB7cn0KYWxsU3RyaXBzUHJpY2VsaXN0IDwtIGxpc3QoKQpmb3IoeWVhciBpbiB5ZWFyX3N0cmlwcyl7CiAgb3Bwb3J0dW5pdHlfZGF0ZXMgPC0gd2l0aCh5ZWFyLCBEYXRlW3llYXIkUmVjb21tZW5kYXRpb24gPT0gIjUgLSBHcmVhdCBoZWRnaW5nIG9wcG9ydHVuaXR5IiB8IHllYXIkUmVjb21tZW5kYXRpb24gPT0gIjQgLSBWZXJ5IGdvb2QgaGVkZ2luZyBvcHBvcnR1bml0eSJdKQoKICBhbGxwcmljZWxpc3QgPC0gbGlzdCgpCiAgZm9yKGkgaW4gb3Bwb3J0dW5pdHlfZGF0ZXMpewogICAgI3ByaW50KGFzLmNoYXJhY3Rlcihhcy5EYXRlKGFzLlBPU0lYY3QoaSwgb3JpZ2luPSIxOTcwLTAxLTAxIikpKSkKICAgICNwcmludChZXzE0QU1bWV8xNEFNJERhdGU9PWksICJQcmljZSJdKQogICAgb3Bwb3J0dW5pdHlfaW5kZXggPC0gd2hpY2goeWVhciREYXRlID09IGkpCiAgICBvcHBvcnR1bml0eV9wcmljZSA8LSB5ZWFyW29wcG9ydHVuaXR5X2luZGV4LCAiUHJpY2UiXQogICAgaWYob3Bwb3J0dW5pdHlfaW5kZXgrbnJvdyhjbGllbnRfcmVzcG9uc2VzKSA8IChucm93KHllYXIpKzEpKXsKICAgICAgcHJpY2VsaXN0IDwtIGxpc3QoeWVhcltvcHBvcnR1bml0eV9pbmRleDoob3Bwb3J0dW5pdHlfaW5kZXgrbnJvdyhjbGllbnRfcmVzcG9uc2VzKS0xKSwgIlByaWNlIl0pCiAgICAgIG5hbWVzKHByaWNlbGlzdCkgPC0gYXMuY2hhcmFjdGVyKGFzLkRhdGUoYXMuUE9TSVhjdChpLCBvcmlnaW49IjE5NzAtMDEtMDEiKSkpCiAgICB9CiAgICBlbHNlewogICAgICBwcmljZWxpc3QgPC0gbGlzdCh5ZWFyW29wcG9ydHVuaXR5X2luZGV4Om5yb3coeWVhciksICJQcmljZSJdKQogICAgICBuYW1lcyhwcmljZWxpc3QpIDwtIGFzLmNoYXJhY3Rlcihhcy5EYXRlKGFzLlBPU0lYY3QoaSwgb3JpZ2luPSIxOTcwLTAxLTAxIikpKQogICAgfQogICAgYWxscHJpY2VsaXN0IDwtIGFwcGVuZChhbGxwcmljZWxpc3QsIHByaWNlbGlzdCkKICB9CiAgYWxsU3RyaXBzUHJpY2VsaXN0IDwtIGFwcGVuZChhbGxTdHJpcHNQcmljZWxpc3QsIGFsbHByaWNlbGlzdCkKfQoKYXZnX2NsaWVudF9yZXNwb25zZXMgPC0gbGlzdChyb3dNZWFucyhjbGllbnRfcmVzcG9uc2VzKSkKYXZlcmFnZWRfcHJpY2VzIDwtIGxpc3QoKQpmb3IoaSBpbiAxOmxlbmd0aChhbGxTdHJpcHNQcmljZWxpc3QpKXsKICBmcmFjIDwtIGxpc3QoKGMoYXZnX2NsaWVudF9yZXNwb25zZXNbWzFdXVsxOmxlbmd0aChhbGxTdHJpcHNQcmljZWxpc3RbW2ldXSldKSkvc3VtKGMoYXZnX2NsaWVudF9yZXNwb25zZXNbWzFdXVsxOmxlbmd0aChhbGxTdHJpcHNQcmljZWxpc3RbW2ldXSldKSkpCiAgYXZlcmFnZWRfcHJpY2VzIDwtIGFwcGVuZChhdmVyYWdlZF9wcmljZXMsIGZyYWMpCn0KZnJhY3Rpb25fcHJpY2VzIDwtIE1hcCgnKicsIGF2ZXJhZ2VkX3ByaWNlcywgYWxsU3RyaXBzUHJpY2VsaXN0KQphdmVyYWdlZF9wcmljZXMgPC0gbGlzdCgpCmZvcihpIGluIDE6bGVuZ3RoKGZyYWN0aW9uX3ByaWNlcykpewogIGF2ZXJhZ2VkX3ByaWNlcyA8LSBhcHBlbmQoYXZlcmFnZWRfcHJpY2VzLCBzdW0oZnJhY3Rpb25fcHJpY2VzW1tpXV0pKQp9CgphdmVyYWdlZF9wcmljZXMgPC0gYyhzYXBwbHkoYXZlcmFnZWRfcHJpY2VzLCAnWycsIGk9MSkpCmNvbnRyYWN0bmRhdGVzIDwtIGxpc3QoRGF0ZT1wYXRfb3V0cHV0W3BhdF9vdXRwdXQkUmVjb21tZW5kYXRpb249PSI1IC0gR3JlYXQgaGVkZ2luZyBvcHBvcnR1bml0eSIgfCBwYXRfb3V0cHV0JFJlY29tbWVuZGF0aW9uPT0iNCAtIFZlcnkgZ29vZCBoZWRnaW5nIG9wcG9ydHVuaXR5IiwgIkRhdGUiXSwgQ29udHJhY3Q9cGF0X291dHB1dFtwYXRfb3V0cHV0JFJlY29tbWVuZGF0aW9uPT0iNSAtIEdyZWF0IGhlZGdpbmcgb3Bwb3J0dW5pdHkiIHwgcGF0X291dHB1dCRSZWNvbW1lbmRhdGlvbj09IjQgLSBWZXJ5IGdvb2QgaGVkZ2luZyBvcHBvcnR1bml0eSIsICJDb250cmFjdCJdKQpkYXRlcyA8LSBjb250cmFjdG5kYXRlcyREYXRlCmNvbnRyYWN0cyA8LSBjb250cmFjdG5kYXRlcyRDb250cmFjdAphdmVyYWdlZF9wcmljZXMgPC0gZGF0YS5mcmFtZShDb250cmFjdD1jb250cmFjdHMsIERhdGU9ZGF0ZXMsIFByaWNlPWF2ZXJhZ2VkX3ByaWNlcykKcGF0X291dHB1dF9tb2RpZmllZCA8LSBwYXRfb3V0cHV0CgpwYXRfbW9kX2luZGV4IDwtIHdoaWNoKG91dGVyKHBhdF9vdXRwdXRfbW9kaWZpZWQkQ29udHJhY3QsIGF2ZXJhZ2VkX3ByaWNlcyRDb250cmFjdCwgIj09IikgICAgICAgICAgICAgICAgICAgICAgJiBvdXRlcihwYXRfb3V0cHV0X21vZGlmaWVkJERhdGUsIGF2ZXJhZ2VkX3ByaWNlcyREYXRlLCAiPT0iKSwKICAgICAgICAgICAgICAgICAgICAgICBhcnIuaW5kID0gVFJVRSkKCmZvciAoaWR4IGluIDE6bnJvdyhwYXRfbW9kX2luZGV4KSl7CiAgcGF0X291dHB1dF9tb2RpZmllZCRQcmljZVtwYXRfbW9kX2luZGV4W2lkeCwicm93Il1dIDwtIGF2ZXJhZ2VkX3ByaWNlcyRQcmljZVtpZHhdCn0KCnBhdF9vdXRwdXRfbW9kaWZpZWQgPC0gcGF0X291dHB1dF9tb2RpZmllZFtvcmRlcihwYXRfb3V0cHV0X21vZGlmaWVkJENvbnRyYWN0KSwgXQptb2RpZmllZF9ZXzE0QU0gPC0gcGF0X291dHB1dF9tb2RpZmllZFtwYXRfb3V0cHV0X21vZGlmaWVkJENvbnRyYWN0PT0iWV8xNEFNIixdCm1vZGlmaWVkX1lfMTUgPC0gcGF0X291dHB1dF9tb2RpZmllZFtwYXRfb3V0cHV0X21vZGlmaWVkJENvbnRyYWN0PT0iWV8xNSIsXQptb2RpZmllZF9ZXzE1QU0gPC0gcGF0X291dHB1dF9tb2RpZmllZFtwYXRfb3V0cHV0X21vZGlmaWVkJENvbnRyYWN0PT0iWV8xNUFNIixdCm1vZGlmaWVkX1lfMTYgPC0gcGF0X291dHB1dF9tb2RpZmllZFtwYXRfb3V0cHV0X21vZGlmaWVkJENvbnRyYWN0PT0iWV8xNiIsXQptb2RpZmllZF9ZXzE2QU0gPC0gcGF0X291dHB1dF9tb2RpZmllZFtwYXRfb3V0cHV0X21vZGlmaWVkJENvbnRyYWN0PT0iWV8xNkFNIixdCm1vZGlmaWVkX1lfMTcgPC0gcGF0X291dHB1dF9tb2RpZmllZFtwYXRfb3V0cHV0X21vZGlmaWVkJENvbnRyYWN0PT0iWV8xNyIsXQptb2RpZmllZF9ZXzE3QU0gPC0gcGF0X291dHB1dF9tb2RpZmllZFtwYXRfb3V0cHV0X21vZGlmaWVkJENvbnRyYWN0PT0iWV8xN0FNIixdCmBgYAoKCjxicj48YnI+ClZpb2xpbiBwbG90cyBzaG93aW5nIHdlaWdodGVkIGF2ZXJhZ2UgcHJpY2VzIGZvciBHcmVhdCAmIFYuIEdvb2QgaGVkZ2luZyBvcHBvcnR1bml0aWVzIHRha2luZyBmdXR1cmUgMjggZGF5cyBhcyBjbGllbnQgcmVzcG9uc2VzLyBkZWxheXMgaW50byBjb25zaWRlcmF0aW9uLiBBIHJlZCBkb3QgcmVwcmVzZW50cyAiNSAtIEdyZWF0IGhlZGdpbmcgb3Bwb3J0dW5pdHkiIGFuZCBhIHllbGxvdyBkb3QgcmVwcmVzZW50cyAiNCAtIFZlcnkgZ29vZCBoZWRnaW5nIG9wcG9ydHVuaXR5Ii4gSG9yaXpvbnRhbCBjcm9zc2JhcihibGFjaykgc2hvd3MgdGhlIG1lZGlhbiBwcmljZSBmb3IgdGhhdCBzdHJpcC4KCmBgYHtyfQpnZ3Bsb3Qod2lkdGggPSA5NTAsIHBhdF9vdXRwdXRfbW9kaWZpZWQsIGFlcyhDb250cmFjdCwgUHJpY2UpKSArIGdlb21fdmlvbGluKGFlcyhmaWxsID0gQ29udHJhY3QpKSArIHNjYWxlX2ZpbGxfbWFudWFsKHZhbHVlcz1jKCIjQjRFMEQyIiwgIiNGQ0M2QjMiLCAiI0M2Q0ZFNCIsICIjRjJDNUUwIiwgIiNEM0VBQUQiLCAiI0ZFRUJBMSIsICIjRjFFMUNBIikpICsgZ2VvbV9wb2ludChkYXRhPXBhdF9vdXRwdXRbcGF0X291dHB1dCRSZWNvbW1lbmRhdGlvbj09IjUgLSBHcmVhdCBoZWRnaW5nIG9wcG9ydHVuaXR5IixdLCBhZXMoQ29udHJhY3QsIFByaWNlKSwgY29sb3IgPSAiI0I0MDYxOSIsIHBvc2l0aW9uID0gcG9zaXRpb25faml0dGVyKDAuMDkpLCBzaXplID0gMC41KSArIGdlb21fcG9pbnQoZGF0YT1wYXRfb3V0cHV0W3BhdF9vdXRwdXQkUmVjb21tZW5kYXRpb249PSI0IC0gVmVyeSBnb29kIGhlZGdpbmcgb3Bwb3J0dW5pdHkiLF0sIGFlcyhDb250cmFjdCwgUHJpY2UpLCBjb2xvciA9ICIjRTU2NjIxIiwgcG9zaXRpb24gPSBwb3NpdGlvbl9qaXR0ZXIoMC4wOSksIHNpemUgPSAwLjUpICsgc3RhdF9zdW1tYXJ5KGZ1bi55ID0gIm1lZGlhbiIsIGZ1bi55bWluID0ibWVkaWFuIiwgZnVuLnltYXggPSJtZWRpYW4iLCBnZW9tID0iY3Jvc3NiYXIiLCB3aWR0aD0wLjIsIGZhdHRlbiA9IDEpCmBgYApUaGUgcGxvdCBkb2Vzbid0IGxvb2sgdmVyeSBkaWZmZXJlbnQgZnJvbSBwcmV2aW91cyB0aGUgdmlvbGluIHBsb3Qgb3IgdGhlIGNoYW5nZXMgYXJlIGluc2lnbmlmaWNhbnQgdG8gYmUgdmlzaWJsZSBhdCBoaWdoIGxldmVsLgoKPGJyPjxicj4KQmFzaWMgc3RhdGlzdGljcyB3aXRoIHdlaWdodGVkIHByaWNlcyBmb3IgR3JlYXQgJiBWLiBHb29kIGhlZGdpbmcgUHJpY2VzLgpgYGB7cn0KeWVhcl9zdHJpcHMgPC0gbGlzdChtb2RpZmllZF9ZXzE0QU0sIG1vZGlmaWVkX1lfMTUsIG1vZGlmaWVkX1lfMTVBTSwgbW9kaWZpZWRfWV8xNiwgbW9kaWZpZWRfWV8xNkFNLCBtb2RpZmllZF9ZXzE3LCBtb2RpZmllZF9ZXzE3QU0pCmZyYWN0aW9uIDwtIGZ1bmN0aW9uKHN0cmlwKXsKICB5ZWFyT3JkZXJlZEJ5UHJpY2UgPC0gc3RyaXBbb3JkZXIoLXN0cmlwJFByaWNlKSxdCiAgZmlyc3RfcXVhcnRpbGUgPC0geWVhck9yZGVyZWRCeVByaWNlW2MoMTp0cnVuYyhucm93KHllYXJPcmRlcmVkQnlQcmljZSkvNCkpLF0KICBzZWNvbmRfcXVhcnRpbGUgPC0geWVhck9yZGVyZWRCeVByaWNlW2MoKHRydW5jKG5yb3coeWVhck9yZGVyZWRCeVByaWNlKS80KSsxKTp0cnVuYyhucm93KHllYXJPcmRlcmVkQnlQcmljZSkvMikpLF0KICB0aGlyZF9xdWFydGlsZSA8LSB5ZWFyT3JkZXJlZEJ5UHJpY2VbYygodHJ1bmMobnJvdyh5ZWFyT3JkZXJlZEJ5UHJpY2UpLzIpKzEpOnRydW5jKG5yb3coeWVhck9yZGVyZWRCeVByaWNlKSozLzQpKSxdCiAgZm91cnRoX3F1YXJ0aWxlIDwtIHllYXJPcmRlcmVkQnlQcmljZVtjKCh0cnVuYyhucm93KHllYXJPcmRlcmVkQnlQcmljZSkqMy80KSsxKTp0cnVuYyhucm93KHllYXJPcmRlcmVkQnlQcmljZSkpKSxdCiAgCiAgbnVtT2ZHcmVhdEluRmlyc3RRdWFydGlsZSA8LSBzdW0oZmlyc3RfcXVhcnRpbGUkUmVjb21tZW5kYXRpb24gPT0gIjUgLSBHcmVhdCBoZWRnaW5nIG9wcG9ydHVuaXR5IikKICBudW1PZlZlcnlHb29kSW5GaXJzdFF1YXJ0aWxlIDwtIHN1bShmaXJzdF9xdWFydGlsZSRSZWNvbW1lbmRhdGlvbiA9PSAiNCAtIFZlcnkgZ29vZCBoZWRnaW5nIG9wcG9ydHVuaXR5IikKICBudW1PZkdyZWF0SW5TZWNvbmRRdWFydGlsZSA8LSBzdW0oc2Vjb25kX3F1YXJ0aWxlJFJlY29tbWVuZGF0aW9uID09ICI1IC0gR3JlYXQgaGVkZ2luZyBvcHBvcnR1bml0eSIpCiAgbnVtT2ZWZXJ5R29vZEluU2Vjb25kUXVhcnRpbGUgPC0gc3VtKHNlY29uZF9xdWFydGlsZSRSZWNvbW1lbmRhdGlvbiA9PSAiNCAtIFZlcnkgZ29vZCBoZWRnaW5nIG9wcG9ydHVuaXR5IikKICBudW1PZkdyZWF0SW5UaGlyZFF1YXJ0aWxlIDwtIHN1bSh0aGlyZF9xdWFydGlsZSRSZWNvbW1lbmRhdGlvbiA9PSAiNSAtIEdyZWF0IGhlZGdpbmcgb3Bwb3J0dW5pdHkiKQogIG51bU9mVmVyeUdvb2RJblRoaXJkUXVhcnRpbGUgPC0gc3VtKHRoaXJkX3F1YXJ0aWxlJFJlY29tbWVuZGF0aW9uID09ICI0IC0gVmVyeSBnb29kIGhlZGdpbmcgb3Bwb3J0dW5pdHkiKQogIG51bU9mR3JlYXRJbkZvdXJ0aFF1YXJ0aWxlIDwtIHN1bShmb3VydGhfcXVhcnRpbGUkUmVjb21tZW5kYXRpb24gPT0gIjUgLSBHcmVhdCBoZWRnaW5nIG9wcG9ydHVuaXR5IikKICBudW1PZlZlcnlHb29kSW5Gb3VydGhRdWFydGlsZSA8LSBzdW0oZm91cnRoX3F1YXJ0aWxlJFJlY29tbWVuZGF0aW9uID09ICI0IC0gVmVyeSBnb29kIGhlZGdpbmcgb3Bwb3J0dW5pdHkiKQogIG51bU9mT3BwSW5GaXJzdFF1YXJ0aWxlIDwtIG51bU9mR3JlYXRJbkZpcnN0UXVhcnRpbGUgKyBudW1PZlZlcnlHb29kSW5GaXJzdFF1YXJ0aWxlCiAgbnVtT2ZPcHBJblNlY29uZFF1YXJ0aWxlIDwtIG51bU9mR3JlYXRJblNlY29uZFF1YXJ0aWxlICsgbnVtT2ZWZXJ5R29vZEluU2Vjb25kUXVhcnRpbGUKICBudW1PZk9wcEluVGhpcmRRdWFydGlsZSA8LSBudW1PZkdyZWF0SW5UaGlyZFF1YXJ0aWxlICsgbnVtT2ZWZXJ5R29vZEluVGhpcmRRdWFydGlsZQogIG51bU9mT3BwSW5Gb3VydGhRdWFydGlsZSA8LSBudW1PZkdyZWF0SW5Gb3VydGhRdWFydGlsZSArIG51bU9mVmVyeUdvb2RJbkZvdXJ0aFF1YXJ0aWxlCiAgY2F0KCJUb3RhbCBuby4gb2YgR3JlYXQgb3IgVi4gR29vZCBoZWRnaW5nIG9wcG9ydHVuaXRpZXMgZm9yIHRoZSBzdHJpcCIsc3RyaXAkQ29udHJhY3RbMV0sIjoiLG51bU9mT3BwSW5GaXJzdFF1YXJ0aWxlICsgbnVtT2ZPcHBJblNlY29uZFF1YXJ0aWxlICsgbnVtT2ZPcHBJblRoaXJkUXVhcnRpbGUgKyBudW1PZk9wcEluRm91cnRoUXVhcnRpbGUsICJcbiIgKQogIGNhdCgiTm8uIG9mIEdyZWF0IG9yIFYuIEdvb2QgaGVkZ2luZyBvcHBvcnR1bml0aWVzIGluIHRoZSB0b3AgcXVhcnRlcigwLTI1JSwgZmlyc3QgcXVhcnRpbGUpIHByaWNlcyBmb3IgdGhlIHN0cmlwIixzdHJpcCRDb250cmFjdFsxXSwiOiIsbnVtT2ZPcHBJbkZpcnN0UXVhcnRpbGUsICJcbiIpCiAgY2F0KCJOby4gb2YgR3JlYXQgb3IgVi4gR29vZCBoZWRnaW5nIG9wcG9ydHVuaXRpZXMgaW4gdGhlIG5leHQgcXVhcnRlcigyNSUtNTAlLCBzZWNvbmQgcXVhcnRpbGUpIHByaWNlcyBmb3IgdGhlIHN0cmlwIixzdHJpcCRDb250cmFjdFsxXSwiOiIsbnVtT2ZPcHBJblNlY29uZFF1YXJ0aWxlLCAiXG4iKQogIGNhdCgiTm8uIG9mIEdyZWF0IG9yIFYuIEdvb2QgaGVkZ2luZyBvcHBvcnR1bml0aWVzIGluIHRoZSBuZXh0IHF1YXJ0ZXIoNTAlLTc1JSwgdGhpcmQgcXVhcnRpbGUpIHByaWNlcyBmb3IgdGhlIHN0cmlwIixzdHJpcCRDb250cmFjdFsxXSwiOiIsbnVtT2ZPcHBJblRoaXJkUXVhcnRpbGUsICJcbiIpCiAgY2F0KCJOby4gb2YgR3JlYXQgb3IgVi4gR29vZCBoZWRnaW5nIG9wcG9ydHVuaXRpZXMgaW4gdGhlIGJvdHRvbSBxdWFydGVyKDc1JS0xMDAlLCBmb3VydGggcXVhcnRpbGUpIHByaWNlcyBmb3IgdGhlIHN0cmlwIixzdHJpcCRDb250cmFjdFsxXSwiOiIsbnVtT2ZPcHBJbkZvdXJ0aFF1YXJ0aWxlLCAiXG5cbiIpCiAgCn0KCmZvcihpIGluIHllYXJfc3RyaXBzKXsKICBmcmFjdGlvbihpKQp9CmBgYAoKPGJyPjxicj4KUmVsYXRpdmUgYmFyIHBsb3Qgc2hvd2luZyB0aGUgZGlmZmVyZW5jZSBiZXR3ZWVuIHdlaWdodGVkIGF2ZXJhZ2UgcHJpY2VzIGZvciBoZWRnaW5nIG9wcG9ydHVuaXRpZXMgVnMuIGFjdHVhbCBwcmljZXMgb24gdGhlIGRheSBvZiBHcmVhdCBvciBWLiBHb29kIGhlZGdpbmcgb3Bwb3J0dW5pdGllcy4KYGBge3J9Cm1vZGlmaWVkX29wcCA8LSBwYXRfb3V0cHV0X21vZGlmaWVkW3BhdF9vdXRwdXRfbW9kaWZpZWQkUmVjb21tZW5kYXRpb249PSI1IC0gR3JlYXQgaGVkZ2luZyBvcHBvcnR1bml0eSIgfCBwYXRfb3V0cHV0X21vZGlmaWVkJFJlY29tbWVuZGF0aW9uPT0iNCAtIFZlcnkgZ29vZCBoZWRnaW5nIG9wcG9ydHVuaXR5IiwgIlByaWNlIl0Kb3BwIDwtIHBhdF9vdXRwdXRbcGF0X291dHB1dCRSZWNvbW1lbmRhdGlvbj09IjUgLSBHcmVhdCBoZWRnaW5nIG9wcG9ydHVuaXR5IiB8CiAgICAgICAgICAgICAgICAgICAgcGF0X291dHB1dCRSZWNvbW1lbmRhdGlvbj09IjQgLSBWZXJ5IGdvb2QgaGVkZ2luZyBvcHBvcnR1bml0eSIsICJQcmljZSJdCnggPC0gcGF0X291dHB1dFtwYXRfb3V0cHV0JFJlY29tbWVuZGF0aW9uPT0iNSAtIEdyZWF0IGhlZGdpbmcgb3Bwb3J0dW5pdHkiIHwgcGF0X291dHB1dCRSZWNvbW1lbmRhdGlvbj09IjQgLSBWZXJ5IGdvb2QgaGVkZ2luZyBvcHBvcnR1bml0eSIsICJEYXRlIl0KeSA8LSB1bmxpc3QoTWFwKCctJywgbW9kaWZpZWRfb3BwLCBvcHApKQpkYXRhIDwtIGRhdGEuZnJhbWUoeCwgeSkKcGxvdF9seShkYXRhLCB4ID0gfngsIHkgPSB+eSwgdHlwZSA9ICdiYXInLCB3aWR0aCA9IDk1MCkgJT4lIGxheW91dChob3Zlcm1vZGU9ImNvbXBhcmUiLCAKICAgICAgICAgdGl0bGUgPSAnT3ZlcnZpZXcgb2YgbW9kaWZpZWQgZWZmZWN0aXZlIGhlZGdpbmcgb3Bwb3J0dW5pdHkgcHJpY2VzJywKICAgICAgICAgeGF4aXMgPSBsaXN0KHRpdGxlID0gJ0RhdGVzJyksCiAgICAgICAgIHlheGlzID0gbGlzdCh0aXRsZSA9ICdEaWZmZXJlbmNlKGVmZmVjdGl2ZSAtIGFjdHVhbCknKSkKYGBgCjxicj48YnI+CmBgYHtyfQpsb3dlcl9wcmljZXMgPC0gc3VtKHk8MCkKaGlnaGVyX3ByaWNlcyA8LSBzdW0oeT4wKQp1bmNoYW5nZWRfcHJpY2VzIDwtIHN1bSh5PT0wKQpwZXJjZW50X2xvd2VyX3ByaWNlIDwtIDEwMCpsb3dlcl9wcmljZXMvbnJvdyhhdmVyYWdlZF9wcmljZXMpCnBlcmNlbnRfaGlnaGVyX3ByaWNlIDwtIDEwMCpoaWdoZXJfcHJpY2VzL25yb3coYXZlcmFnZWRfcHJpY2VzKQpwZXJjZW50X3NhbWVfcHJpY2UgPC0gMTAwKnVuY2hhbmdlZF9wcmljZXMvbnJvdyhhdmVyYWdlZF9wcmljZXMpCmNhdCgiV2VpZ2h0ZWQgYXZlcmFnZSBncmVhdCAmIHZlcnkgZ29vZCBoZWRnaW5nIG9wcG9ydHVuaXR5IHByaWNlcyB0aGF0IGFyZSBsb3dlciB0aGFuIHRoZSBhY3R1YWwgcHJpY2VzIixwZXJjZW50X2xvd2VyX3ByaWNlLCIlXG5XZWlnaHRlZCBhdmVyYWdlIGdyZWF0ICYgdmVyeSBnb29kIGhlZGdpbmcgb3Bwb3J0dW5pdHkgcHJpY2VzIHRoYXQgYXJlIGhpZ2hlciB0aGFuIHRoZSBhY3R1YWwgcHJpY2VzIiwgcGVyY2VudF9oaWdoZXJfcHJpY2UsICIlXG5XZWlnaHRlZCBhdmVyYWdlIGdyZWF0ICYgdmVyeSBnb29kIGhlZGdpbmcgb3Bwb3J0dW5pdHkgcHJpY2VzIHRoYXQgYXJlIHNhbWUgYXMgdGhlIGFjdHVhbCBwcmljZXMiLHBlcmNlbnRfc2FtZV9wcmljZSwiJVxuXG4iKQpgYGAKCjxicj48YnI+ClJlbGF0aXZlIGJhciBwbG90IHNob3dpbmcgdGhlIGRpZmZlcmVuY2UgYmV0d2VlbiB3ZWlnaHRlZCBhdmVyYWdlIHByaWNlcyBmb3IgaGVkZ2luZyBvcHBvcnR1bml0aWVzIFZzLiBhY3R1YWwgcHJpY2VzIG9uIHRoZSBkYXkgb2YgR3JlYXQgb3IgVi4gR29vZCBoZWRnaW5nIG9wcG9ydHVuaXRpZXMgZm9yIGVhY2ggc3RyaXAuCmBgYHtyfQptb2RpZmllZF9vcHBfWV8xNEFNIDwtIG1vZGlmaWVkX1lfMTRBTVttb2RpZmllZF9ZXzE0QU0kUmVjb21tZW5kYXRpb249PSI1IC0gR3JlYXQgaGVkZ2luZyBvcHBvcnR1bml0eSIgfCBtb2RpZmllZF9ZXzE0QU0kUmVjb21tZW5kYXRpb249PSI0IC0gVmVyeSBnb29kIGhlZGdpbmcgb3Bwb3J0dW5pdHkiLCAiUHJpY2UiXQpvcHBfWV8xNEFNIDwtIFlfMTRBTVtZXzE0QU0kUmVjb21tZW5kYXRpb249PSI1IC0gR3JlYXQgaGVkZ2luZyBvcHBvcnR1bml0eSIgfAogICAgICAgICAgICAgICAgICAgIFlfMTRBTSRSZWNvbW1lbmRhdGlvbj09IjQgLSBWZXJ5IGdvb2QgaGVkZ2luZyBvcHBvcnR1bml0eSIsICJQcmljZSJdCnhfWV8xNEFNIDwtIG1vZGlmaWVkX1lfMTRBTVttb2RpZmllZF9ZXzE0QU0kUmVjb21tZW5kYXRpb249PSI1IC0gR3JlYXQgaGVkZ2luZyBvcHBvcnR1bml0eSIgfCBtb2RpZmllZF9ZXzE0QU0kUmVjb21tZW5kYXRpb249PSI0IC0gVmVyeSBnb29kIGhlZGdpbmcgb3Bwb3J0dW5pdHkiLCAiRGF0ZSJdCnlfWV8xNEFNIDwtIHVubGlzdChNYXAoJy0nLCBtb2RpZmllZF9vcHBfWV8xNEFNLCBvcHBfWV8xNEFNKSkKZGF0YV9ZXzE0QU0gPC0gZGF0YS5mcmFtZSh4X1lfMTRBTSwgeV9ZXzE0QU0pCnAxIDwtIHBsb3RfbHkoZGF0YSwgeCA9IH54X1lfMTRBTSwgeSA9IH55X1lfMTRBTSwgdHlwZSA9ICdiYXInLCBuYW1lID0gJ1lfMTRBTScsIHdpZHRoID0gOTUwLCBoZWlnaHQgPSA2NTApICU+JSBsYXlvdXQoaG92ZXJtb2RlPSJjb21wYXJlIiwgeGF4aXMgPSBsaXN0KHRpdGxlID0gJ0RhdGVzJyksIHlheGlzID0gbGlzdCh0aXRsZSA9ICdEaWZmZXJlbmNlJykpCgptb2RpZmllZF9vcHBfWV8xNSA8LSBtb2RpZmllZF9ZXzE1W21vZGlmaWVkX1lfMTUkUmVjb21tZW5kYXRpb249PSI1IC0gR3JlYXQgaGVkZ2luZyBvcHBvcnR1bml0eSIgfCBtb2RpZmllZF9ZXzE1JFJlY29tbWVuZGF0aW9uPT0iNCAtIFZlcnkgZ29vZCBoZWRnaW5nIG9wcG9ydHVuaXR5IiwgIlByaWNlIl0Kb3BwX1lfMTUgPC0gWV8xNVtZXzE1JFJlY29tbWVuZGF0aW9uPT0iNSAtIEdyZWF0IGhlZGdpbmcgb3Bwb3J0dW5pdHkiIHwKICAgICAgICAgICAgICAgICAgICBZXzE1JFJlY29tbWVuZGF0aW9uPT0iNCAtIFZlcnkgZ29vZCBoZWRnaW5nIG9wcG9ydHVuaXR5IiwgIlByaWNlIl0KeF9ZXzE1IDwtIG1vZGlmaWVkX1lfMTVbbW9kaWZpZWRfWV8xNSRSZWNvbW1lbmRhdGlvbj09IjUgLSBHcmVhdCBoZWRnaW5nIG9wcG9ydHVuaXR5IiB8IG1vZGlmaWVkX1lfMTUkUmVjb21tZW5kYXRpb249PSI0IC0gVmVyeSBnb29kIGhlZGdpbmcgb3Bwb3J0dW5pdHkiLCAiRGF0ZSJdCnlfWV8xNSA8LSB1bmxpc3QoTWFwKCctJywgbW9kaWZpZWRfb3BwX1lfMTUsIG9wcF9ZXzE1KSkKZGF0YV9ZXzE1IDwtIGRhdGEuZnJhbWUoeF9ZXzE1LCB5X1lfMTUpCnAyIDwtIHBsb3RfbHkoZGF0YSwgeCA9IH54X1lfMTUsIHkgPSB+eV9ZXzE1LCB0eXBlID0gJ2JhcicsIG5hbWUgPSAnWV8xNScsIHdpZHRoID0gOTUwKSAlPiUgbGF5b3V0KGhvdmVybW9kZT0iY29tcGFyZSIsIAogICAgICAgICB4YXhpcyA9IGxpc3QodGl0bGUgPSAnRGF0ZXMnKSwKICAgICAgICAgeWF4aXMgPSBsaXN0KHRpdGxlID0gJ0RpZmZlcmVuY2UnKSkKCm1vZGlmaWVkX29wcF9ZXzE1QU0gPC0gbW9kaWZpZWRfWV8xNUFNW21vZGlmaWVkX1lfMTVBTSRSZWNvbW1lbmRhdGlvbj09IjUgLSBHcmVhdCBoZWRnaW5nIG9wcG9ydHVuaXR5IiB8IG1vZGlmaWVkX1lfMTVBTSRSZWNvbW1lbmRhdGlvbj09IjQgLSBWZXJ5IGdvb2QgaGVkZ2luZyBvcHBvcnR1bml0eSIsICJQcmljZSJdCm9wcF9ZXzE1QU0gPC0gWV8xNUFNW1lfMTVBTSRSZWNvbW1lbmRhdGlvbj09IjUgLSBHcmVhdCBoZWRnaW5nIG9wcG9ydHVuaXR5IiB8CiAgICAgICAgICAgICAgICAgICAgWV8xNUFNJFJlY29tbWVuZGF0aW9uPT0iNCAtIFZlcnkgZ29vZCBoZWRnaW5nIG9wcG9ydHVuaXR5IiwgIlByaWNlIl0KeF9ZXzE1QU0gPC0gbW9kaWZpZWRfWV8xNUFNW21vZGlmaWVkX1lfMTVBTSRSZWNvbW1lbmRhdGlvbj09IjUgLSBHcmVhdCBoZWRnaW5nIG9wcG9ydHVuaXR5IiB8IG1vZGlmaWVkX1lfMTVBTSRSZWNvbW1lbmRhdGlvbj09IjQgLSBWZXJ5IGdvb2QgaGVkZ2luZyBvcHBvcnR1bml0eSIsICJEYXRlIl0KeV9ZXzE1QU0gPC0gdW5saXN0KE1hcCgnLScsIG1vZGlmaWVkX29wcF9ZXzE1QU0sIG9wcF9ZXzE1QU0pKQpkYXRhX1lfMTVBTSA8LSBkYXRhLmZyYW1lKHhfWV8xNUFNLCB5X1lfMTVBTSkKcDMgPC0gcGxvdF9seShkYXRhLCB4ID0gfnhfWV8xNUFNLCB5ID0gfnlfWV8xNUFNLCB0eXBlID0gJ2JhcicsIG5hbWUgPSAnWV8xNUFNJywgd2lkdGggPSA5NTApICU+JSBsYXlvdXQoaG92ZXJtb2RlPSJjb21wYXJlIiwgCiAgICAgICAgIHhheGlzID0gbGlzdCh0aXRsZSA9ICdEYXRlcycpLAogICAgICAgICB5YXhpcyA9IGxpc3QodGl0bGUgPSAnRGlmZmVyZW5jZScpKQoKbW9kaWZpZWRfb3BwX1lfMTYgPC0gbW9kaWZpZWRfWV8xNlttb2RpZmllZF9ZXzE2JFJlY29tbWVuZGF0aW9uPT0iNSAtIEdyZWF0IGhlZGdpbmcgb3Bwb3J0dW5pdHkiIHwgbW9kaWZpZWRfWV8xNiRSZWNvbW1lbmRhdGlvbj09IjQgLSBWZXJ5IGdvb2QgaGVkZ2luZyBvcHBvcnR1bml0eSIsICJQcmljZSJdCm9wcF9ZXzE2IDwtIFlfMTZbWV8xNiRSZWNvbW1lbmRhdGlvbj09IjUgLSBHcmVhdCBoZWRnaW5nIG9wcG9ydHVuaXR5IiB8CiAgICAgICAgICAgICAgICAgICAgWV8xNiRSZWNvbW1lbmRhdGlvbj09IjQgLSBWZXJ5IGdvb2QgaGVkZ2luZyBvcHBvcnR1bml0eSIsICJQcmljZSJdCnhfWV8xNiA8LSBtb2RpZmllZF9ZXzE2W21vZGlmaWVkX1lfMTYkUmVjb21tZW5kYXRpb249PSI1IC0gR3JlYXQgaGVkZ2luZyBvcHBvcnR1bml0eSIgfCBtb2RpZmllZF9ZXzE2JFJlY29tbWVuZGF0aW9uPT0iNCAtIFZlcnkgZ29vZCBoZWRnaW5nIG9wcG9ydHVuaXR5IiwgIkRhdGUiXQp5X1lfMTYgPC0gdW5saXN0KE1hcCgnLScsIG1vZGlmaWVkX29wcF9ZXzE2LCBvcHBfWV8xNikpCmRhdGFfWV8xNiA8LSBkYXRhLmZyYW1lKHhfWV8xNiwgeV9ZXzE2KQpwNCA8LSBwbG90X2x5KGRhdGEsIHggPSB+eF9ZXzE2LCB5ID0gfnlfWV8xNiwgdHlwZSA9ICdiYXInLCBuYW1lID0gJ1lfMTYnLCB3aWR0aCA9IDk1MCkgJT4lIGxheW91dChob3Zlcm1vZGU9ImNvbXBhcmUiLCAKICAgICAgICAgeGF4aXMgPSBsaXN0KHRpdGxlID0gJ0RhdGVzJyksCiAgICAgICAgIHlheGlzID0gbGlzdCh0aXRsZSA9ICdEaWZmZXJlbmNlJykpCgptb2RpZmllZF9vcHBfWV8xNkFNIDwtIG1vZGlmaWVkX1lfMTZBTVttb2RpZmllZF9ZXzE2QU0kUmVjb21tZW5kYXRpb249PSI1IC0gR3JlYXQgaGVkZ2luZyBvcHBvcnR1bml0eSIgfCBtb2RpZmllZF9ZXzE2QU0kUmVjb21tZW5kYXRpb249PSI0IC0gVmVyeSBnb29kIGhlZGdpbmcgb3Bwb3J0dW5pdHkiLCAiUHJpY2UiXQpvcHBfWV8xNkFNIDwtIFlfMTZBTVtZXzE2QU0kUmVjb21tZW5kYXRpb249PSI1IC0gR3JlYXQgaGVkZ2luZyBvcHBvcnR1bml0eSIgfAogICAgICAgICAgICAgICAgICAgIFlfMTZBTSRSZWNvbW1lbmRhdGlvbj09IjQgLSBWZXJ5IGdvb2QgaGVkZ2luZyBvcHBvcnR1bml0eSIsICJQcmljZSJdCnhfWV8xNkFNIDwtIG1vZGlmaWVkX1lfMTZBTVttb2RpZmllZF9ZXzE2QU0kUmVjb21tZW5kYXRpb249PSI1IC0gR3JlYXQgaGVkZ2luZyBvcHBvcnR1bml0eSIgfCBtb2RpZmllZF9ZXzE2QU0kUmVjb21tZW5kYXRpb249PSI0IC0gVmVyeSBnb29kIGhlZGdpbmcgb3Bwb3J0dW5pdHkiLCAiRGF0ZSJdCnlfWV8xNkFNIDwtIHVubGlzdChNYXAoJy0nLCBtb2RpZmllZF9vcHBfWV8xNkFNLCBvcHBfWV8xNkFNKSkKZGF0YV9ZXzE2QU0gPC0gZGF0YS5mcmFtZSh4X1lfMTZBTSwgeV9ZXzE2QU0pCnA1IDwtIHBsb3RfbHkoZGF0YSwgeCA9IH54X1lfMTZBTSwgeSA9IH55X1lfMTZBTSwgdHlwZSA9ICdiYXInLCBuYW1lID0gJ1lfMTZBTScsIHdpZHRoID0gOTUwKSAlPiUgbGF5b3V0KGhvdmVybW9kZT0iY29tcGFyZSIsIAogICAgICAgICB4YXhpcyA9IGxpc3QodGl0bGUgPSAnRGF0ZXMnKSwKICAgICAgICAgeWF4aXMgPSBsaXN0KHRpdGxlID0gJ0RpZmZlcmVuY2UnKSkKCm1vZGlmaWVkX29wcF9ZXzE3IDwtIG1vZGlmaWVkX1lfMTdbbW9kaWZpZWRfWV8xNyRSZWNvbW1lbmRhdGlvbj09IjUgLSBHcmVhdCBoZWRnaW5nIG9wcG9ydHVuaXR5IiB8IG1vZGlmaWVkX1lfMTckUmVjb21tZW5kYXRpb249PSI0IC0gVmVyeSBnb29kIGhlZGdpbmcgb3Bwb3J0dW5pdHkiLCAiUHJpY2UiXQpvcHBfWV8xNyA8LSBZXzE3W1lfMTckUmVjb21tZW5kYXRpb249PSI1IC0gR3JlYXQgaGVkZ2luZyBvcHBvcnR1bml0eSIgfAogICAgICAgICAgICAgICAgICAgIFlfMTckUmVjb21tZW5kYXRpb249PSI0IC0gVmVyeSBnb29kIGhlZGdpbmcgb3Bwb3J0dW5pdHkiLCAiUHJpY2UiXQp4X1lfMTcgPC0gbW9kaWZpZWRfWV8xN1ttb2RpZmllZF9ZXzE3JFJlY29tbWVuZGF0aW9uPT0iNSAtIEdyZWF0IGhlZGdpbmcgb3Bwb3J0dW5pdHkiIHwgbW9kaWZpZWRfWV8xNyRSZWNvbW1lbmRhdGlvbj09IjQgLSBWZXJ5IGdvb2QgaGVkZ2luZyBvcHBvcnR1bml0eSIsICJEYXRlIl0KeV9ZXzE3IDwtIHVubGlzdChNYXAoJy0nLCBtb2RpZmllZF9vcHBfWV8xNywgb3BwX1lfMTcpKQpkYXRhX1lfMTcgPC0gZGF0YS5mcmFtZSh4X1lfMTcsIHlfWV8xNykKcDYgPC0gcGxvdF9seShkYXRhLCB4ID0gfnhfWV8xNywgeSA9IH55X1lfMTcsIHR5cGUgPSAnYmFyJywgbmFtZSA9ICdZXzE3Jywgd2lkdGggPSA5NTApICU+JSBsYXlvdXQoaG92ZXJtb2RlPSJjb21wYXJlIiwgCiAgICAgICAgIHhheGlzID0gbGlzdCh0aXRsZSA9ICdEYXRlcycpLAogICAgICAgICB5YXhpcyA9IGxpc3QodGl0bGUgPSAnRGlmZmVyZW5jZScpKQoKbW9kaWZpZWRfb3BwX1lfMTdBTSA8LSBtb2RpZmllZF9ZXzE3QU1bbW9kaWZpZWRfWV8xN0FNJFJlY29tbWVuZGF0aW9uPT0iNSAtIEdyZWF0IGhlZGdpbmcgb3Bwb3J0dW5pdHkiIHwgbW9kaWZpZWRfWV8xN0FNJFJlY29tbWVuZGF0aW9uPT0iNCAtIFZlcnkgZ29vZCBoZWRnaW5nIG9wcG9ydHVuaXR5IiwgIlByaWNlIl0Kb3BwX1lfMTdBTSA8LSBZXzE3QU1bWV8xN0FNJFJlY29tbWVuZGF0aW9uPT0iNSAtIEdyZWF0IGhlZGdpbmcgb3Bwb3J0dW5pdHkiIHwKICAgICAgICAgICAgICAgICAgICBZXzE3QU0kUmVjb21tZW5kYXRpb249PSI0IC0gVmVyeSBnb29kIGhlZGdpbmcgb3Bwb3J0dW5pdHkiLCAiUHJpY2UiXQp4X1lfMTdBTSA8LSBtb2RpZmllZF9ZXzE3QU1bbW9kaWZpZWRfWV8xN0FNJFJlY29tbWVuZGF0aW9uPT0iNSAtIEdyZWF0IGhlZGdpbmcgb3Bwb3J0dW5pdHkiIHwgbW9kaWZpZWRfWV8xN0FNJFJlY29tbWVuZGF0aW9uPT0iNCAtIFZlcnkgZ29vZCBoZWRnaW5nIG9wcG9ydHVuaXR5IiwgIkRhdGUiXQp5X1lfMTdBTSA8LSB1bmxpc3QoTWFwKCctJywgbW9kaWZpZWRfb3BwX1lfMTdBTSwgb3BwX1lfMTdBTSkpCmRhdGFfWV8xN0FNIDwtIGRhdGEuZnJhbWUoeF9ZXzE3QU0sIHlfWV8xN0FNKQpwNyA8LSBwbG90X2x5KGRhdGEsIHggPSB+eF9ZXzE3QU0sIHkgPSB+eV9ZXzE3QU0sIHR5cGUgPSAnYmFyJywgbmFtZSA9ICdZXzE3QU0nLCB3aWR0aCA9IDk1MCkgJT4lIGxheW91dChob3Zlcm1vZGU9ImNvbXBhcmUiLCAKICAgICAgICAgeGF4aXMgPSBsaXN0KHRpdGxlID0gJ0RhdGVzJyksCiAgICAgICAgIHlheGlzID0gbGlzdCh0aXRsZSA9ICdEaWZmZXJlbmNlJykpCnN1YnBsb3QocDEsIHAyLCBwMywgcDQsIHA1LCBwNiwgcDcsIG5yb3dzID0gNCwgc2hhcmVZID0gVFJVRSkKYGBgCgo8YnI+PGJyPgpgYGB7cn0KbG93ZXJfcHJpY2VzX1lfMTRBTSA8LSBzdW0oeV9ZXzE0QU08MCkKaGlnaGVyX3ByaWNlc19ZXzE0QU0gPC0gc3VtKHlfWV8xNEFNPjApCnVuY2hhbmdlZF9wcmljZXNfWV8xNEFNIDwtIHN1bSh5X1lfMTRBTT09MCkKcGVyY2VudF9sb3dlcl9wcmljZV9ZXzE0QU0gPC0gMTAwKmxvd2VyX3ByaWNlc19ZXzE0QU0vbGVuZ3RoKFlfMTRBTVtZXzE0QU0kUmVjb21tZW5kYXRpb249PSI1IC0gR3JlYXQgaGVkZ2luZyBvcHBvcnR1bml0eSIgfCBZXzE0QU0kUmVjb21tZW5kYXRpb249PSI0IC0gVmVyeSBnb29kIGhlZGdpbmcgb3Bwb3J0dW5pdHkiLCAiUHJpY2UiXSkKcGVyY2VudF9oaWdoZXJfcHJpY2VfWV8xNEFNIDwtIDEwMCpoaWdoZXJfcHJpY2VzX1lfMTRBTS9sZW5ndGgoWV8xNEFNW1lfMTRBTSRSZWNvbW1lbmRhdGlvbj09IjUgLSBHcmVhdCBoZWRnaW5nIG9wcG9ydHVuaXR5IiB8IFlfMTRBTSRSZWNvbW1lbmRhdGlvbj09IjQgLSBWZXJ5IGdvb2QgaGVkZ2luZyBvcHBvcnR1bml0eSIsICJQcmljZSJdKQoKcGVyY2VudF9zYW1lX3ByaWNlX1lfMTRBTSA8LSAxMDAqdW5jaGFuZ2VkX3ByaWNlc19ZXzE0QU0vbGVuZ3RoKFlfMTRBTVtZXzE0QU0kUmVjb21tZW5kYXRpb249PSI1IC0gR3JlYXQgaGVkZ2luZyBvcHBvcnR1bml0eSIgfCBZXzE0QU0kUmVjb21tZW5kYXRpb249PSI0IC0gVmVyeSBnb29kIGhlZGdpbmcgb3Bwb3J0dW5pdHkiLCAiUHJpY2UiXSkKCmNhdCgiRm9yIHRoZSBzdHJpcCBZXzE0QU0gd2VpZ2h0ZWQgYXZlcmFnZSBncmVhdCAmIHZlcnkgZ29vZCBoZWRnaW5nIG9wcG9ydHVuaXR5IHByaWNlcyB0aGF0IGFyZSBsb3dlciB0aGFuIHRoZSBhY3R1YWwgcHJpY2VzIixwZXJjZW50X2xvd2VyX3ByaWNlX1lfMTRBTSwiJVxuRm9yIHRoZSBzdHJpcCBZXzE0QU0gd2VpZ2h0ZWQgYXZlcmFnZSBncmVhdCAmIHZlcnkgZ29vZCBoZWRnaW5nIG9wcG9ydHVuaXR5IHByaWNlcyB0aGF0IGFyZSBoaWdoZXIgdGhhbiB0aGUgYWN0dWFsIHByaWNlcyIsIHBlcmNlbnRfaGlnaGVyX3ByaWNlX1lfMTRBTSwgIiVcbkZvciB0aGUgc3RyaXAgWV8xNEFNIHdlaWdodGVkIGF2ZXJhZ2UgZ3JlYXQgJiB2ZXJ5IGdvb2QgaGVkZ2luZyBvcHBvcnR1bml0eSBwcmljZXMgdGhhdCBhcmUgc2FtZSBhcyB0aGUgYWN0dWFsIHByaWNlcyIscGVyY2VudF9zYW1lX3ByaWNlX1lfMTRBTSwiJVxuXG4iKQoKbG93ZXJfcHJpY2VzX1lfMTUgPC0gc3VtKHlfWV8xNTwwKQpoaWdoZXJfcHJpY2VzX1lfMTUgPC0gc3VtKHlfWV8xNT4wKQp1bmNoYW5nZWRfcHJpY2VzX1lfMTUgPC0gc3VtKHlfWV8xNT09MCkKcGVyY2VudF9sb3dlcl9wcmljZV9ZXzE1IDwtIDEwMCpsb3dlcl9wcmljZXNfWV8xNS9sZW5ndGgoWV8xNVtZXzE1JFJlY29tbWVuZGF0aW9uPT0iNSAtIEdyZWF0IGhlZGdpbmcgb3Bwb3J0dW5pdHkiIHwgWV8xNSRSZWNvbW1lbmRhdGlvbj09IjQgLSBWZXJ5IGdvb2QgaGVkZ2luZyBvcHBvcnR1bml0eSIsICJQcmljZSJdKQpwZXJjZW50X2hpZ2hlcl9wcmljZV9ZXzE1IDwtIDEwMCpoaWdoZXJfcHJpY2VzX1lfMTUvbGVuZ3RoKFlfMTVbWV8xNSRSZWNvbW1lbmRhdGlvbj09IjUgLSBHcmVhdCBoZWRnaW5nIG9wcG9ydHVuaXR5IiB8IFlfMTUkUmVjb21tZW5kYXRpb249PSI0IC0gVmVyeSBnb29kIGhlZGdpbmcgb3Bwb3J0dW5pdHkiLCAiUHJpY2UiXSkKCnBlcmNlbnRfc2FtZV9wcmljZV9ZXzE1IDwtIDEwMCp1bmNoYW5nZWRfcHJpY2VzX1lfMTUvbGVuZ3RoKFlfMTVbWV8xNSRSZWNvbW1lbmRhdGlvbj09IjUgLSBHcmVhdCBoZWRnaW5nIG9wcG9ydHVuaXR5IiB8IFlfMTUkUmVjb21tZW5kYXRpb249PSI0IC0gVmVyeSBnb29kIGhlZGdpbmcgb3Bwb3J0dW5pdHkiLCAiUHJpY2UiXSkKCmNhdCgiRm9yIHRoZSBzdHJpcCBZXzE1IHdlaWdodGVkIGF2ZXJhZ2UgZ3JlYXQgJiB2ZXJ5IGdvb2QgaGVkZ2luZyBvcHBvcnR1bml0eSBwcmljZXMgdGhhdCBhcmUgbG93ZXIgdGhhbiB0aGUgYWN0dWFsIHByaWNlcyIscGVyY2VudF9sb3dlcl9wcmljZV9ZXzE1LCIlXG5Gb3IgdGhlIHN0cmlwIFlfMTUgd2VpZ2h0ZWQgYXZlcmFnZSBncmVhdCAmIHZlcnkgZ29vZCBoZWRnaW5nIG9wcG9ydHVuaXR5IHByaWNlcyB0aGF0IGFyZSBoaWdoZXIgdGhhbiB0aGUgYWN0dWFsIHByaWNlcyIsIHBlcmNlbnRfaGlnaGVyX3ByaWNlX1lfMTUsICIlXG5Gb3IgdGhlIHN0cmlwIFlfMTUgd2VpZ2h0ZWQgYXZlcmFnZSBncmVhdCAmIHZlcnkgZ29vZCBoZWRnaW5nIG9wcG9ydHVuaXR5IHByaWNlcyB0aGF0IGFyZSBzYW1lIGFzIHRoZSBhY3R1YWwgcHJpY2VzIixwZXJjZW50X3NhbWVfcHJpY2VfWV8xNSwiJVxuXG4iKQoKbG93ZXJfcHJpY2VzX1lfMTVBTSA8LSBzdW0oeV9ZXzE1QU08MCkKaGlnaGVyX3ByaWNlc19ZXzE1QU0gPC0gc3VtKHlfWV8xNUFNPjApCnVuY2hhbmdlZF9wcmljZXNfWV8xNUFNIDwtIHN1bSh5X1lfMTVBTT09MCkKcGVyY2VudF9sb3dlcl9wcmljZV9ZXzE1QU0gPC0gMTAwKmxvd2VyX3ByaWNlc19ZXzE1QU0vbGVuZ3RoKFlfMTVBTVtZXzE1QU0kUmVjb21tZW5kYXRpb249PSI1IC0gR3JlYXQgaGVkZ2luZyBvcHBvcnR1bml0eSIgfCBZXzE1QU0kUmVjb21tZW5kYXRpb249PSI0IC0gVmVyeSBnb29kIGhlZGdpbmcgb3Bwb3J0dW5pdHkiLCAiUHJpY2UiXSkKcGVyY2VudF9oaWdoZXJfcHJpY2VfWV8xNUFNIDwtIDEwMCpoaWdoZXJfcHJpY2VzX1lfMTVBTS9sZW5ndGgoWV8xNUFNW1lfMTVBTSRSZWNvbW1lbmRhdGlvbj09IjUgLSBHcmVhdCBoZWRnaW5nIG9wcG9ydHVuaXR5IiB8IFlfMTVBTSRSZWNvbW1lbmRhdGlvbj09IjQgLSBWZXJ5IGdvb2QgaGVkZ2luZyBvcHBvcnR1bml0eSIsICJQcmljZSJdKQoKcGVyY2VudF9zYW1lX3ByaWNlX1lfMTVBTSA8LSAxMDAqdW5jaGFuZ2VkX3ByaWNlc19ZXzE1QU0vbGVuZ3RoKFlfMTVBTVtZXzE1QU0kUmVjb21tZW5kYXRpb249PSI1IC0gR3JlYXQgaGVkZ2luZyBvcHBvcnR1bml0eSIgfCBZXzE1QU0kUmVjb21tZW5kYXRpb249PSI0IC0gVmVyeSBnb29kIGhlZGdpbmcgb3Bwb3J0dW5pdHkiLCAiUHJpY2UiXSkKCmNhdCgiRm9yIHRoZSBzdHJpcCBZXzE1QU0gd2VpZ2h0ZWQgYXZlcmFnZSBncmVhdCAmIHZlcnkgZ29vZCBoZWRnaW5nIG9wcG9ydHVuaXR5IHByaWNlcyB0aGF0IGFyZSBsb3dlciB0aGFuIHRoZSBhY3R1YWwgcHJpY2VzIixwZXJjZW50X2xvd2VyX3ByaWNlX1lfMTVBTSwiJVxuRm9yIHRoZSBzdHJpcCBZXzE1QU0gd2VpZ2h0ZWQgYXZlcmFnZSBncmVhdCAmIHZlcnkgZ29vZCBoZWRnaW5nIG9wcG9ydHVuaXR5IHByaWNlcyB0aGF0IGFyZSBoaWdoZXIgdGhhbiB0aGUgYWN0dWFsIHByaWNlcyIsIHBlcmNlbnRfaGlnaGVyX3ByaWNlX1lfMTVBTSwgIiVcbkZvciB0aGUgc3RyaXAgWV8xNUFNIHdlaWdodGVkIGF2ZXJhZ2UgZ3JlYXQgJiB2ZXJ5IGdvb2QgaGVkZ2luZyBvcHBvcnR1bml0eSBwcmljZXMgdGhhdCBhcmUgc2FtZSBhcyB0aGUgYWN0dWFsIHByaWNlcyIscGVyY2VudF9zYW1lX3ByaWNlX1lfMTVBTSwiJVxuXG4iKQoKbG93ZXJfcHJpY2VzX1lfMTYgPC0gc3VtKHlfWV8xNjwwKQpoaWdoZXJfcHJpY2VzX1lfMTYgPC0gc3VtKHlfWV8xNj4wKQp1bmNoYW5nZWRfcHJpY2VzX1lfMTYgPC0gc3VtKHlfWV8xNj09MCkKcGVyY2VudF9sb3dlcl9wcmljZV9ZXzE2IDwtIDEwMCpsb3dlcl9wcmljZXNfWV8xNi9sZW5ndGgoWV8xNltZXzE2JFJlY29tbWVuZGF0aW9uPT0iNSAtIEdyZWF0IGhlZGdpbmcgb3Bwb3J0dW5pdHkiIHwgWV8xNiRSZWNvbW1lbmRhdGlvbj09IjQgLSBWZXJ5IGdvb2QgaGVkZ2luZyBvcHBvcnR1bml0eSIsICJQcmljZSJdKQpwZXJjZW50X2hpZ2hlcl9wcmljZV9ZXzE2IDwtIDEwMCpoaWdoZXJfcHJpY2VzX1lfMTYvbGVuZ3RoKFlfMTZbWV8xNiRSZWNvbW1lbmRhdGlvbj09IjUgLSBHcmVhdCBoZWRnaW5nIG9wcG9ydHVuaXR5IiB8IFlfMTYkUmVjb21tZW5kYXRpb249PSI0IC0gVmVyeSBnb29kIGhlZGdpbmcgb3Bwb3J0dW5pdHkiLCAiUHJpY2UiXSkKCnBlcmNlbnRfc2FtZV9wcmljZV9ZXzE2IDwtIDEwMCp1bmNoYW5nZWRfcHJpY2VzX1lfMTYvbGVuZ3RoKFlfMTZbWV8xNiRSZWNvbW1lbmRhdGlvbj09IjUgLSBHcmVhdCBoZWRnaW5nIG9wcG9ydHVuaXR5IiB8IFlfMTYkUmVjb21tZW5kYXRpb249PSI0IC0gVmVyeSBnb29kIGhlZGdpbmcgb3Bwb3J0dW5pdHkiLCAiUHJpY2UiXSkKCmNhdCgiRm9yIHRoZSBzdHJpcCBZXzE2IHdlaWdodGVkIGF2ZXJhZ2UgZ3JlYXQgJiB2ZXJ5IGdvb2QgaGVkZ2luZyBvcHBvcnR1bml0eSBwcmljZXMgdGhhdCBhcmUgbG93ZXIgdGhhbiB0aGUgYWN0dWFsIHByaWNlcyIscGVyY2VudF9sb3dlcl9wcmljZV9ZXzE2LCIlXG5Gb3IgdGhlIHN0cmlwIFlfMTYgd2VpZ2h0ZWQgYXZlcmFnZSBncmVhdCAmIHZlcnkgZ29vZCBoZWRnaW5nIG9wcG9ydHVuaXR5IHByaWNlcyB0aGF0IGFyZSBoaWdoZXIgdGhhbiB0aGUgYWN0dWFsIHByaWNlcyIsIHBlcmNlbnRfaGlnaGVyX3ByaWNlX1lfMTYsICIlXG5Gb3IgdGhlIHN0cmlwIFlfMTYgd2VpZ2h0ZWQgYXZlcmFnZSBncmVhdCAmIHZlcnkgZ29vZCBoZWRnaW5nIG9wcG9ydHVuaXR5IHByaWNlcyB0aGF0IGFyZSBzYW1lIGFzIHRoZSBhY3R1YWwgcHJpY2VzIixwZXJjZW50X3NhbWVfcHJpY2VfWV8xNiwiJVxuXG4iKQoKbG93ZXJfcHJpY2VzX1lfMTZBTSA8LSBzdW0oeV9ZXzE2QU08MCkKaGlnaGVyX3ByaWNlc19ZXzE2QU0gPC0gc3VtKHlfWV8xNkFNPjApCnVuY2hhbmdlZF9wcmljZXNfWV8xNkFNIDwtIHN1bSh5X1lfMTZBTT09MCkKcGVyY2VudF9sb3dlcl9wcmljZV9ZXzE2QU0gPC0gMTAwKmxvd2VyX3ByaWNlc19ZXzE2QU0vbGVuZ3RoKFlfMTZBTVtZXzE2QU0kUmVjb21tZW5kYXRpb249PSI1IC0gR3JlYXQgaGVkZ2luZyBvcHBvcnR1bml0eSIgfCBZXzE2QU0kUmVjb21tZW5kYXRpb249PSI0IC0gVmVyeSBnb29kIGhlZGdpbmcgb3Bwb3J0dW5pdHkiLCAiUHJpY2UiXSkKcGVyY2VudF9oaWdoZXJfcHJpY2VfWV8xNkFNIDwtIDEwMCpoaWdoZXJfcHJpY2VzX1lfMTZBTS9sZW5ndGgoWV8xNkFNW1lfMTZBTSRSZWNvbW1lbmRhdGlvbj09IjUgLSBHcmVhdCBoZWRnaW5nIG9wcG9ydHVuaXR5IiB8IFlfMTZBTSRSZWNvbW1lbmRhdGlvbj09IjQgLSBWZXJ5IGdvb2QgaGVkZ2luZyBvcHBvcnR1bml0eSIsICJQcmljZSJdKQoKcGVyY2VudF9zYW1lX3ByaWNlX1lfMTZBTSA8LSAxMDAqdW5jaGFuZ2VkX3ByaWNlc19ZXzE2QU0vbGVuZ3RoKFlfMTZBTVtZXzE2QU0kUmVjb21tZW5kYXRpb249PSI1IC0gR3JlYXQgaGVkZ2luZyBvcHBvcnR1bml0eSIgfCBZXzE2QU0kUmVjb21tZW5kYXRpb249PSI0IC0gVmVyeSBnb29kIGhlZGdpbmcgb3Bwb3J0dW5pdHkiLCAiUHJpY2UiXSkKCmNhdCgiRm9yIHRoZSBzdHJpcCBZXzE2QU0gd2VpZ2h0ZWQgYXZlcmFnZSBncmVhdCAmIHZlcnkgZ29vZCBoZWRnaW5nIG9wcG9ydHVuaXR5IHByaWNlcyB0aGF0IGFyZSBsb3dlciB0aGFuIHRoZSBhY3R1YWwgcHJpY2VzIixwZXJjZW50X2xvd2VyX3ByaWNlX1lfMTZBTSwiJVxuRm9yIHRoZSBzdHJpcCBZXzE2QU0gd2VpZ2h0ZWQgYXZlcmFnZSBncmVhdCAmIHZlcnkgZ29vZCBoZWRnaW5nIG9wcG9ydHVuaXR5IHByaWNlcyB0aGF0IGFyZSBoaWdoZXIgdGhhbiB0aGUgYWN0dWFsIHByaWNlcyIsIHBlcmNlbnRfaGlnaGVyX3ByaWNlX1lfMTZBTSwgIiVcbkZvciB0aGUgc3RyaXAgWV8xNkFNIHdlaWdodGVkIGF2ZXJhZ2UgZ3JlYXQgJiB2ZXJ5IGdvb2QgaGVkZ2luZyBvcHBvcnR1bml0eSBwcmljZXMgdGhhdCBhcmUgc2FtZSBhcyB0aGUgYWN0dWFsIHByaWNlcyIscGVyY2VudF9zYW1lX3ByaWNlX1lfMTZBTSwiJVxuXG4iKQoKbG93ZXJfcHJpY2VzX1lfMTcgPC0gc3VtKHlfWV8xNzwwKQpoaWdoZXJfcHJpY2VzX1lfMTcgPC0gc3VtKHlfWV8xNz4wKQp1bmNoYW5nZWRfcHJpY2VzX1lfMTcgPC0gc3VtKHlfWV8xNz09MCkKcGVyY2VudF9sb3dlcl9wcmljZV9ZXzE3IDwtIDEwMCpsb3dlcl9wcmljZXNfWV8xNy9sZW5ndGgoWV8xN1tZXzE3JFJlY29tbWVuZGF0aW9uPT0iNSAtIEdyZWF0IGhlZGdpbmcgb3Bwb3J0dW5pdHkiIHwgWV8xNyRSZWNvbW1lbmRhdGlvbj09IjQgLSBWZXJ5IGdvb2QgaGVkZ2luZyBvcHBvcnR1bml0eSIsICJQcmljZSJdKQpwZXJjZW50X2hpZ2hlcl9wcmljZV9ZXzE3IDwtIDEwMCpoaWdoZXJfcHJpY2VzX1lfMTcvbGVuZ3RoKFlfMTdbWV8xNyRSZWNvbW1lbmRhdGlvbj09IjUgLSBHcmVhdCBoZWRnaW5nIG9wcG9ydHVuaXR5IiB8IFlfMTckUmVjb21tZW5kYXRpb249PSI0IC0gVmVyeSBnb29kIGhlZGdpbmcgb3Bwb3J0dW5pdHkiLCAiUHJpY2UiXSkKCnBlcmNlbnRfc2FtZV9wcmljZV9ZXzE3IDwtIDEwMCp1bmNoYW5nZWRfcHJpY2VzX1lfMTcvbGVuZ3RoKFlfMTdbWV8xNyRSZWNvbW1lbmRhdGlvbj09IjUgLSBHcmVhdCBoZWRnaW5nIG9wcG9ydHVuaXR5IiB8IFlfMTckUmVjb21tZW5kYXRpb249PSI0IC0gVmVyeSBnb29kIGhlZGdpbmcgb3Bwb3J0dW5pdHkiLCAiUHJpY2UiXSkKCmNhdCgiRm9yIHRoZSBzdHJpcCBZXzE3IHdlaWdodGVkIGF2ZXJhZ2UgZ3JlYXQgJiB2ZXJ5IGdvb2QgaGVkZ2luZyBvcHBvcnR1bml0eSBwcmljZXMgdGhhdCBhcmUgbG93ZXIgdGhhbiB0aGUgYWN0dWFsIHByaWNlcyIscGVyY2VudF9sb3dlcl9wcmljZV9ZXzE3LCIlXG5Gb3IgdGhlIHN0cmlwIFlfMTcgd2VpZ2h0ZWQgYXZlcmFnZSBncmVhdCAmIHZlcnkgZ29vZCBoZWRnaW5nIG9wcG9ydHVuaXR5IHByaWNlcyB0aGF0IGFyZSBoaWdoZXIgdGhhbiB0aGUgYWN0dWFsIHByaWNlcyIsIHBlcmNlbnRfaGlnaGVyX3ByaWNlX1lfMTcsICIlXG5Gb3IgdGhlIHN0cmlwIFlfMTcgd2VpZ2h0ZWQgYXZlcmFnZSBncmVhdCAmIHZlcnkgZ29vZCBoZWRnaW5nIG9wcG9ydHVuaXR5IHByaWNlcyB0aGF0IGFyZSBzYW1lIGFzIHRoZSBhY3R1YWwgcHJpY2VzIixwZXJjZW50X3NhbWVfcHJpY2VfWV8xNywiJVxuXG4iKQoKbG93ZXJfcHJpY2VzX1lfMTdBTSA8LSBzdW0oeV9ZXzE3QU08MCkKaGlnaGVyX3ByaWNlc19ZXzE3QU0gPC0gc3VtKHlfWV8xN0FNPjApCnVuY2hhbmdlZF9wcmljZXNfWV8xN0FNIDwtIHN1bSh5X1lfMTdBTT09MCkKcGVyY2VudF9sb3dlcl9wcmljZV9ZXzE3QU0gPC0gMTAwKmxvd2VyX3ByaWNlc19ZXzE3QU0vbGVuZ3RoKFlfMTdBTVtZXzE3QU0kUmVjb21tZW5kYXRpb249PSI1IC0gR3JlYXQgaGVkZ2luZyBvcHBvcnR1bml0eSIgfCBZXzE3QU0kUmVjb21tZW5kYXRpb249PSI0IC0gVmVyeSBnb29kIGhlZGdpbmcgb3Bwb3J0dW5pdHkiLCAiUHJpY2UiXSkKcGVyY2VudF9oaWdoZXJfcHJpY2VfWV8xN0FNIDwtIDEwMCpoaWdoZXJfcHJpY2VzX1lfMTdBTS9sZW5ndGgoWV8xN0FNW1lfMTdBTSRSZWNvbW1lbmRhdGlvbj09IjUgLSBHcmVhdCBoZWRnaW5nIG9wcG9ydHVuaXR5IiB8IFlfMTdBTSRSZWNvbW1lbmRhdGlvbj09IjQgLSBWZXJ5IGdvb2QgaGVkZ2luZyBvcHBvcnR1bml0eSIsICJQcmljZSJdKQoKcGVyY2VudF9zYW1lX3ByaWNlX1lfMTdBTSA8LSAxMDAqdW5jaGFuZ2VkX3ByaWNlc19ZXzE3QU0vbGVuZ3RoKFlfMTdBTVtZXzE3QU0kUmVjb21tZW5kYXRpb249PSI1IC0gR3JlYXQgaGVkZ2luZyBvcHBvcnR1bml0eSIgfCBZXzE3QU0kUmVjb21tZW5kYXRpb249PSI0IC0gVmVyeSBnb29kIGhlZGdpbmcgb3Bwb3J0dW5pdHkiLCAiUHJpY2UiXSkKCmNhdCgiRm9yIHRoZSBzdHJpcCBZXzE3QU0gd2VpZ2h0ZWQgYXZlcmFnZSBncmVhdCAmIHZlcnkgZ29vZCBoZWRnaW5nIG9wcG9ydHVuaXR5IHByaWNlcyB0aGF0IGFyZSBsb3dlciB0aGFuIHRoZSBhY3R1YWwgcHJpY2VzIixwZXJjZW50X2xvd2VyX3ByaWNlX1lfMTdBTSwiJVxuRm9yIHRoZSBzdHJpcCBZXzE3QU0gd2VpZ2h0ZWQgYXZlcmFnZSBncmVhdCAmIHZlcnkgZ29vZCBoZWRnaW5nIG9wcG9ydHVuaXR5IHByaWNlcyB0aGF0IGFyZSBoaWdoZXIgdGhhbiB0aGUgYWN0dWFsIHByaWNlcyIsIHBlcmNlbnRfaGlnaGVyX3ByaWNlX1lfMTdBTSwgIiVcbkZvciB0aGUgc3RyaXAgWV8xN0FNIHdlaWdodGVkIGF2ZXJhZ2UgZ3JlYXQgJiB2ZXJ5IGdvb2QgaGVkZ2luZyBvcHBvcnR1bml0eSBwcmljZXMgdGhhdCBhcmUgc2FtZSBhcyB0aGUgYWN0dWFsIHByaWNlcyIscGVyY2VudF9zYW1lX3ByaWNlX1lfMTdBTSwiJVxuXG4iKQoKYGBgCgoKXzIpIEF2ZXJhZ2VkIG92ZXIgYXZlcmFnZSBvZiBlYWNoIHllYXI6XwpOdW1iZXIgb2YgY2xpZW50IHJlc3BvbnNlcyBmb3IgZWFjaCBkYXRlIG9mIGEgcGFydGljdWxhciB5ZWFyIGFyZSBhdmVyYWdlZCB0byBnZXQgYW4geWVhcmx5IGF2ZXJhZ2Ugd2hpY2ggYXJlIHRoZW4gc3VtbWVkIHRvZ2V0aGVyIGFuZCBkaXZpZGVkIGJ5IHRvdGFsIG51bWJlciBvZiBjbGllbnQgcmVzcG9uc2VzIGF2ZXJhZ2VkIG92ZXIgZWFjaCB5ZWFyLgoKJCQgQXZlcmFnZVwsY2xpZW50XCxyZXNwb25zZXNcLG9uXCxcLGtee3RofVwsXCxkYXlcLD0gXGZyYWN7XHN1bShZZWFyXCxhdmVyYWdlXCxjbGllbnRcLHJlc3BvbnNlc1wsb25cLGtee3RofVwsZGF5KX17XHN1bShOdW1iZXJcLG9mXCxhdmVyYWdlXCxjbGllbnRcLCByZXNwb25zZXNcLCBmb3JcLCBlYWNoXCwgeWVhcil9ICQkCgpTaW5jZSB0aGVyZSBpc24ndCBtdWNoIG9mIGEgZGlmZmVyZW5jZSBpbiB0aGUgYXZlcmFnZWQgb3V0cHV0cyBmcm9tIGJvdGggYXBwcm9hY2hlcywgd2UgdXNlZCBvbmx5IHRoZSAkMV57c3R9JCBhcHByb2FjaC4KCjxicj48YnI+CgoKIyMjIyNBcmUgdGhlIGRpZmZlcmVuY2VzIGJldHdlZW4gdGhlIGVmZmVjdGl2ZSBhdmVyYWdlZCBwcmljZXMgYW5kIGFjdHVhbCBwcmljZXMgcmVhbGx5IHNpZ25pZmljYW50PwpUbyBldmFsdWF0ZSB0aGUgc2lnbmlmaWNhbmNlIHdlIGRvIGEgc2lnbmlmaWNhbmNlIHRlc3Qgd2l0aCAKCgo=